-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.mjs
More file actions
134 lines (113 loc) · 3.98 KB
/
benchmark.mjs
File metadata and controls
134 lines (113 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env node
import autocannon from 'autocannon';
const API_BASE = 'http://localhost:3000';
const DURATION = 10; // seconds
const CONNECTIONS = 10;
const PIPELINING = 1;
console.log('Black Friday Cache-Aside Performance Benchmark\n');
async function runBenchmark(name, url, description) {
console.log(`\n${'='.repeat(60)}`);
console.log(`${name}`);
console.log(`${description}`);
console.log(`${'='.repeat(60)}\n`);
return new Promise(resolve => {
const instance = autocannon(
{
url,
connections: CONNECTIONS,
pipelining: PIPELINING,
duration: DURATION,
title: name,
},
(err, result) => {
if (err) {
console.error('Error:', err);
resolve(null);
return;
}
console.log(`\nResults:`);
console.log(` Requests: ${result.requests.total} total`);
console.log(
` Throughput: ${result.requests.average.toFixed(2)} req/sec`
);
console.log(` Latency:`);
console.log(` - Average: ${result.latency.mean.toFixed(2)} ms`);
console.log(
` - p50: ${result.latency.p50 || result.latency.median || 0} ms`
);
console.log(
` - p97.5: ${result.latency.p97_5 || result.latency.p975 || 0} ms`
);
console.log(` - p99: ${result.latency.p99 || 0} ms`);
console.log(
` Throughput: ${(result.throughput.mean / 1024 / 1024).toFixed(2)} MB/sec\n`
);
resolve(result);
}
);
autocannon.track(instance, { renderProgressBar: true });
});
}
async function main() {
console.log('Test Configuration:');
console.log(` Duration: ${DURATION} seconds`);
console.log(` Connections: ${CONNECTIONS}`);
console.log(` Target: ${API_BASE}`);
console.log('');
// Test 1: With Cache (Cache-Aside Pattern)
console.log('Testing WITH cache (/cache/:sku)...');
await new Promise(resolve => setTimeout(resolve, 2000));
const withCache = await runBenchmark(
'WITH Cache (Cache-Aside Pattern)',
`${API_BASE}/cache/SKU-1`,
'First request populates cache from DB (~50ms), subsequent requests served from Redis (~2ms)'
);
// Wait between tests
console.log('\nWaiting 3 seconds before next test...\n');
await new Promise(resolve => setTimeout(resolve, 3000));
// Test 2: Without Cache (Direct DB)
console.log('Testing WITHOUT cache (/nocache/:sku)...');
const withoutCache = await runBenchmark(
'WITHOUT Cache (Direct DB Access)',
`${API_BASE}/nocache/SKU-2`,
'Every request hits the database directly (~50ms per request)'
);
// Summary Comparison
if (withCache && withoutCache) {
console.log('\n' + '='.repeat(60));
console.log('PERFORMANCE COMPARISON');
console.log('='.repeat(60) + '\n');
const speedup = withCache.requests.average / withoutCache.requests.average;
const latencyReduction =
((withoutCache.latency.mean - withCache.latency.mean) /
withoutCache.latency.mean) *
100;
console.log('Throughput:');
console.log(
` WITH cache: ${withCache.requests.average.toFixed(2)} req/sec`
);
console.log(
` WITHOUT cache: ${withoutCache.requests.average.toFixed(2)} req/sec`
);
console.log(` Speedup: ${speedup.toFixed(1)}x faster`);
console.log('\nLatency:');
console.log(` WITH cache: ${withCache.latency.mean.toFixed(2)} ms`);
console.log(
` WITHOUT cache: ${withoutCache.latency.mean.toFixed(2)} ms`
);
console.log(
` Reduction: ${latencyReduction.toFixed(1)}% lower latency`
);
console.log('\nKey Takeaway:');
console.log(
` Cache-aside pattern delivers ${speedup.toFixed(1)}x higher throughput`
);
console.log(
` and ${latencyReduction.toFixed(1)}% lower latency under load!\n`
);
}
console.log(
'Benchmark complete! Check Grafana dashboards for real-time metrics.\n'
);
}
main().catch(console.error);