forked from porsager/postgres-benchmarks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
94 lines (82 loc) · 2.52 KB
/
index.js
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
const queries = [
'select',
'select_arg',
'select_args',
'select_where'
]
, clients = [
'postgres',
'pg-promise',
'pg-promise-native',
'pg',
'pg-native',
'slonik'
]
, warmup = 3
, iterations = 10000
, rounds = 5
, variance = false
const series = (fn, xs) => {
const results = []
return xs.reduce((acc, x) => acc.then(() => fn(x).then(r => results.push(r))), Promise.resolve({})).then(() => results)
}
series(test, clients).then(results => {
results.forEach(x => {
x.queries = Object.values(x.queries).filter(q => q.times).map(q => {
q.times = q.times.slice(warmup).map(x => x[0] + x[1] / 1e9)
const avg = (q.times.reduce((a, b) => a + b) / q.times.length)
, sorted = q.times.slice().sort((a, b) => a - b)
return {
time: avg,
variance: 1 / sorted[0] * (sorted[sorted.length - 1] - sorted[0]) * 100
}
})
})
queries.forEach((q, i) =>
results.map(x => x.queries[i]).sort((a, b) => b.time - a.time).forEach((x, i, xs) => {
x.diff = xs[0].time / x.time
})
)
console.log([pad(1, 10, ' ')('client')].concat(queries.map(pad(0, 14, ' '))).join(' | '))
console.log([pad(1, 10, '-')(':')].concat(queries.map(x => ':').map(pad(0, 14, '-'))).join(' | '))
results.forEach(x =>
console.log(
[pad(1, 10, ' ')(x.client)].concat(
x.queries.map(x =>
x.time.toFixed(3) + 's' + ' (' + x.diff.toFixed(1) + 'x)'
).map(pad(0, 14, ' '))
).join(' | ')
)
)
console.log(['client'].concat(queries).join(';'))
results.forEach(x =>
console.log([x.client].concat(x.queries.map(x => x.time.toFixed(3))).join(';').replace(/\./g, ','))
)
process.exit()
})
function pad(p, n, c) {
return x => {
while (x.length < n)
x = p ? x + c : c + x
return x
}
}
async function test(clientName, done) {
return new Promise(async resolve => {
const client = await Promise.resolve(require('./' + clientName))
const q = queries.flatMap(x => Array(rounds + warmup).fill(x))
async function run(x) {
x.start = process.hrtime()
let j = 0
for(let i = 0; i < iterations; i++)
x().then(() => ++j === iterations && next(x))
}
function next(x) {
x && (x.times = (x.times || []).concat([process.hrtime(x.start)]))
q.length
? setTimeout(() => run(client.queries[q.pop()]), 100)
: Promise.resolve(client.end()).then(() => resolve({ client: clientName, queries: client.queries }))
}
next()
})
}