Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add testing section for Accelerate #5401

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions content/800-data-platform/100-accelerate/550-testing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
---
title: 'Testing'
metaTitle: 'Accelerate: Testing'
metaDescription: 'Learn about testing Prisma Accelerate.'
tocDepth: 3
toc: true
---

<TopBlock>

Prisma Accelerate optimizes database interactions through advanced connection pooling and global edge caching. Its connection pooler is available in 16 regions and helps applications load-balance and scale database requests based on demand.

Considering the information above, we recommend testing Accelerate with high volume to see it perform under load.

</TopBlock>

## How Accelerate's connection pool optimizes performance under load

Prisma Accelerate employs a dynamic, serverless connection pooling infrastructure. When a request is made, a connection pool is quickly provisioned for the project in the region assigned while configuring Prisma Accelerate. This connection pool remains active, serving many additional requests while reusing established database connections. The connection pool will disconnect after a period of inactivity, so it’s important to test Prisma Accelerate with a consistent stream of traffic.

**Key Benefits:**

- **Optimized Query Performance:** The serverless connection pooler adapts to the query load, ensuring the database connections are managed efficiently during peak demand.

> Prisma Accelerate’s connection pooler cannot improve the performance of queries in the database. In scenarios where query performance is an issue, we recommend optimizing the Prisma query, applying indexes, or utilizing Accelerate’s edge caching.

- **Maximize Connection Reuse:** Executing a consistent volume of queries helps maintain active instances of Accelerate connection poolers. This increases connection reuse, ensuring faster response times for subsequent queries.

By understanding and harnessing this mechanism, you can ensure that your database queries perform consistently and efficiently at scale.

## Testing Prisma Accelerate connection pooling performance

Below you will find an example of how to test Prisma Accelerate using a sample model:

```prisma
model Notes {
id Int @id @default(autoincrement())
title String
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
}
```

```typescript
import { PrismaClient } from '@prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient().$extends(withAccelerate())

function calculateStatistics(numbers: number[]): {
average: number
p50: number
p75: number
p99: number
} {
if (numbers.length === 0) {
throw new Error('The input array is empty.')
}

// Sort the array in ascending order
numbers.sort((a, b) => a - b)

const sum = numbers.reduce((acc, num) => acc + num, 0)
const count = numbers.length

const average = sum / count
const p50 = getPercentile(numbers, 50)
const p75 = getPercentile(numbers, 75)
const p99 = getPercentile(numbers, 99)

return { average, p50, p75, p99 }
}

function getPercentile(numbers: number[], percentile: number): number {
if (percentile <= 0 || percentile >= 100) {
throw new Error('Percentile must be between 0 and 100.')
}

const index = (percentile / 100) * (numbers.length - 1)
if (Number.isInteger(index)) {
// If the index is an integer, return the corresponding value
return numbers[index]
} else {
// If the index is not an integer, interpolate between two adjacent values
const lowerIndex = Math.floor(index)
const upperIndex = Math.ceil(index)
const lowerValue = numbers[lowerIndex]
const upperValue = numbers[upperIndex]
const interpolationFactor = index - lowerIndex
return lowerValue + (upperValue - lowerValue) * interpolationFactor
}
}

async function main() {
const timings = []

// fire a query before going to the loop
await prisma.notes.findMany({
take: 20,
})

// we recommend testing Prisma Accelerate with a large loop
const LOOP_LENGTH = 10000

for (let i = 0; i < LOOP_LENGTH; i++) {
const start = Date.now()
await prisma.notes.findMany({
take: 20,
})

timings.push(Date.now() - start)
}

const statistics = calculateStatistics(timings)
console.log('Average:', statistics.average)
console.log('P50:', statistics.p50)
console.log('P75:', statistics.p75)
console.log('P99:', statistics.p99)
}

main()
.then(async () => {
await prisma.$disconnect()
})
.catch((e) => {
await prisma.$disconnect()
process.exit(1)
})
```

## Testing Prisma Accelerate caching performance

Prisma Accelerate’s edge cache is also optimized for a high volume of queries. The cache automatically optimizes for repeated queries. As a result, the cache hit rate will increase as the query frequency does. Adding a query result to the cache is also non-blocking, so a short burst of queries might not utilize the cache or a sustained load.

To test Accelerate’s edge caching, you can modify the above script with the below:

```typescript
import { PrismaClient } from '@prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient().$extends(withAccelerate())

function calculateStatistics(numbers: number[]): {
average: number
p50: number
p75: number
p99: number
} {
if (numbers.length === 0) {
throw new Error('The input array is empty.')
}

// Sort the array in ascending order
numbers.sort((a, b) => a - b)

const sum = numbers.reduce((acc, num) => acc + num, 0)
const count = numbers.length

const average = sum / count
const p50 = getPercentile(numbers, 50)
const p75 = getPercentile(numbers, 75)
const p99 = getPercentile(numbers, 99)

return { average, p50, p75, p99 }
}

function getPercentile(numbers: number[], percentile: number): number {
if (percentile <= 0 || percentile >= 100) {
throw new Error('Percentile must be between 0 and 100.')
}

const index = (percentile / 100) * (numbers.length - 1)
if (Number.isInteger(index)) {
// If the index is an integer, return the corresponding value
return numbers[index]
} else {
// If the index is not an integer, interpolate between two adjacent values
const lowerIndex = Math.floor(index)
const upperIndex = Math.ceil(index)
const lowerValue = numbers[lowerIndex]
const upperValue = numbers[upperIndex]
const interpolationFactor = index - lowerIndex
return lowerValue + (upperValue - lowerValue) * interpolationFactor
}
}

async function main() {
const timings = []

// fire a query before going to the loop
await prisma.notes.findMany({
take: 20,
cacheStrategy: {
ttl: 30,
},
})

// we recommend testing Prisma Accelerate with a large loop
const LOOP_LENGTH = 10000

for (let i = 0; i < LOOP_LENGTH; i++) {
const start = Date.now()
await prisma.notes.findMany({
take: 20,
cacheStrategy: {
ttl: 30,
},
})

timings.push(Date.now() - start)
}

const statistics = calculateStatistics(timings)
console.log('Average:', statistics.average)
console.log('P50:', statistics.p50)
console.log('P75:', statistics.p75)
console.log('P99:', statistics.p99)
}

main()
.then(async () => {
await prisma.$disconnect()
})
.catch((e) => {
await prisma.$disconnect()
process.exit(1)
})
```
Loading