Skip to content

Commit b189ed5

Browse files
author
Simone Nigro
committed
perf(bench): add pipeline mode benchmarks
1 parent 587625c commit b189ed5

1 file changed

Lines changed: 113 additions & 44 deletions

File tree

packages/pg/bench.js

Lines changed: 113 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -35,59 +35,128 @@ const bench = async (client, q, time) => {
3535
}
3636
}
3737

38+
// Pipeline mode benchmark - sends N queries concurrently
39+
const benchPipeline = async (client, q, time, batchSize = 100) => {
40+
const start = performance.now()
41+
let count = 0
42+
// eslint-disable-next-line no-constant-condition
43+
while (true) {
44+
const promises = []
45+
for (let i = 0; i < batchSize; i++) {
46+
promises.push(
47+
client.query({
48+
text: q.text,
49+
values: q.values,
50+
rowMode: 'array',
51+
})
52+
)
53+
}
54+
await Promise.all(promises)
55+
count += batchSize
56+
if (performance.now() - start > time) {
57+
return count
58+
}
59+
}
60+
}
61+
3862
const run = async () => {
63+
const seconds = 5
64+
65+
console.log('='.repeat(60))
66+
console.log('STANDARD MODE BENCHMARK')
67+
console.log('='.repeat(60))
68+
3969
const client = new pg.Client()
4070
await client.connect()
41-
console.log('start')
4271
await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)')
4372
await client.query('CREATE TEMP TABLE buf(name TEXT, data BYTEA)')
4473
await bench(client, params, 1000)
45-
console.log('warmup done')
46-
const seconds = 5
74+
console.log('warmup done\n')
4775

48-
for (let i = 0; i < 4; i++) {
49-
let queries = await bench(client, params, seconds * 1000)
50-
console.log('')
51-
console.log('param queries:', queries)
52-
console.log('qps', queries / seconds)
53-
console.log('on my laptop best so far seen 987 qps')
54-
55-
queries = await bench(client, { ...params, name: 'params' }, seconds * 1000)
56-
console.log('')
57-
console.log('named queries:', queries)
58-
console.log('qps', queries / seconds)
59-
console.log('on my laptop best so far seen 937 qps')
60-
61-
console.log('')
62-
queries = await bench(client, seq, seconds * 1000)
63-
console.log('sequence queries:', queries)
64-
console.log('qps', queries / seconds)
65-
console.log('on my laptop best so far seen 2725 qps')
66-
67-
console.log('')
68-
queries = await bench(client, insert, seconds * 1000)
69-
console.log('insert queries:', queries)
70-
console.log('qps', queries / seconds)
71-
console.log('on my laptop best so far seen 27383 qps')
72-
73-
console.log('')
74-
console.log('Warming up bytea test')
75-
await client.query({
76-
text: 'INSERT INTO buf(name, data) VALUES ($1, $2)',
77-
values: ['test', Buffer.allocUnsafe(104857600)],
78-
})
79-
console.log('bytea warmup done')
80-
const start = performance.now()
81-
const results = await client.query('SELECT * FROM buf')
82-
const time = performance.now() - start
83-
console.log('bytea time:', time, 'ms')
84-
console.log('bytea length:', results.rows[0].data.byteLength, 'bytes')
85-
console.log('on my laptop best so far seen 1407ms and 104857600 bytes')
86-
await new Promise((resolve) => setTimeout(resolve, 250))
87-
}
76+
let queries = await bench(client, params, seconds * 1000)
77+
console.log('param queries:', queries)
78+
console.log('qps:', (queries / seconds).toFixed(0))
79+
80+
queries = await bench(client, { ...params, name: 'params' }, seconds * 1000)
81+
console.log('\nnamed queries:', queries)
82+
console.log('qps:', (queries / seconds).toFixed(0))
83+
84+
queries = await bench(client, seq, seconds * 1000)
85+
console.log('\nsequence queries:', queries)
86+
console.log('qps:', (queries / seconds).toFixed(0))
87+
88+
queries = await bench(client, insert, seconds * 1000)
89+
console.log('\ninsert queries:', queries)
90+
console.log('qps:', (queries / seconds).toFixed(0))
8891

8992
await client.end()
90-
await client.end()
93+
94+
console.log('\n')
95+
console.log('='.repeat(60))
96+
console.log('PIPELINE MODE BENCHMARK')
97+
console.log('='.repeat(60))
98+
99+
const pipelineClient = new pg.Client({ pipelineMode: true })
100+
await pipelineClient.connect()
101+
await pipelineClient.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)')
102+
await benchPipeline(pipelineClient, params, 1000)
103+
console.log('warmup done\n')
104+
105+
queries = await benchPipeline(pipelineClient, params, seconds * 1000)
106+
console.log('param queries:', queries)
107+
console.log('qps:', (queries / seconds).toFixed(0))
108+
109+
queries = await benchPipeline(pipelineClient, { ...params, name: 'params' }, seconds * 1000)
110+
console.log('\nnamed queries:', queries)
111+
console.log('qps:', (queries / seconds).toFixed(0))
112+
113+
queries = await benchPipeline(pipelineClient, seq, seconds * 1000)
114+
console.log('\nsequence queries:', queries)
115+
console.log('qps:', (queries / seconds).toFixed(0))
116+
117+
queries = await benchPipeline(pipelineClient, insert, seconds * 1000)
118+
console.log('\ninsert queries:', queries)
119+
console.log('qps:', (queries / seconds).toFixed(0))
120+
121+
await pipelineClient.end()
122+
123+
console.log('\n')
124+
console.log('='.repeat(60))
125+
console.log('COMPARISON: Sequential vs Pipeline (same workload)')
126+
console.log('='.repeat(60))
127+
128+
// Direct comparison: 1000 queries
129+
const numQueries = 1000
130+
131+
const seqClient = new pg.Client()
132+
await seqClient.connect()
133+
134+
console.log(`\nRunning ${numQueries} sequential queries...`)
135+
let start = performance.now()
136+
for (let i = 0; i < numQueries; i++) {
137+
await seqClient.query('SELECT $1::int as i', [i])
138+
}
139+
const seqTime = performance.now() - start
140+
console.log(`Sequential: ${seqTime.toFixed(0)}ms (${((numQueries / seqTime) * 1000).toFixed(0)} qps)`)
141+
142+
await seqClient.end()
143+
144+
const pipClient = new pg.Client({ pipelineMode: true })
145+
await pipClient.connect()
146+
147+
console.log(`Running ${numQueries} pipeline queries...`)
148+
start = performance.now()
149+
const promises = []
150+
for (let i = 0; i < numQueries; i++) {
151+
promises.push(pipClient.query('SELECT $1::int as i', [i]))
152+
}
153+
await Promise.all(promises)
154+
const pipTime = performance.now() - start
155+
console.log(`Pipeline: ${pipTime.toFixed(0)}ms (${((numQueries / pipTime) * 1000).toFixed(0)} qps)`)
156+
157+
console.log(`\nSpeedup: ${(seqTime / pipTime).toFixed(2)}x faster`)
158+
159+
await pipClient.end()
91160
}
92161

93162
run().catch((e) => console.error(e) || process.exit(-1))

0 commit comments

Comments
 (0)