-
Notifications
You must be signed in to change notification settings - Fork 785
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into driver-adapter
- Loading branch information
Showing
4 changed files
with
230 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
228 changes: 228 additions & 0 deletions
228
content/800-data-platform/100-accelerate/550-testing.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.