Skip to content

Commit ad79436

Browse files
committed
Add iterate and clear benchmarks
Undocumented for now because they're in POC stage.
1 parent d36de97 commit ad79436

File tree

5 files changed

+381
-0
lines changed

5 files changed

+381
-0
lines changed

benchmarks/clear.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
'use strict'
2+
3+
const keyspace = require('keyspace')
4+
const window = 1000
5+
const progressWindow = window * 100
6+
7+
exports.defaults = {
8+
benchmark: {
9+
n: 1e6,
10+
valueSize: 100,
11+
keys: 'seq',
12+
values: 'random',
13+
seed: 'seed'
14+
}
15+
}
16+
17+
exports.plot = require('./clear.plot')
18+
19+
exports.run = function (factory, stream, options) {
20+
if (options.n < window) {
21+
throw new RangeError('The "n" option must be >= ' + window)
22+
} else if (options.n % window !== 0) {
23+
throw new Error('The "n" option must be a multiple of ' + window)
24+
}
25+
26+
const generator = keyspace(options.n, options)
27+
28+
stream.write('Elapsed (ms), Entries, Bytes, SMA ns/write, CMA entries/s\n')
29+
30+
function start (db) {
31+
const startTime = Date.now()
32+
33+
let inProgress = 0
34+
let totalDeletes = 0
35+
let totalBytes = 0 // TODO: remove. Can't know
36+
let timesAccum = 0
37+
let elapsed
38+
39+
function report () {
40+
console.log(
41+
'Cleared', options.n, 'entries in',
42+
Math.floor((Date.now() - startTime) / 1e3) + 's'
43+
)
44+
45+
stream.end()
46+
47+
const it = db.iterator()
48+
49+
it.next(function (err, key) {
50+
if (err) throw err
51+
if (key !== undefined) throw new Error('Did not clear all')
52+
53+
it.end(function (err) {
54+
if (err) throw err
55+
56+
db.close(function (err) {
57+
if (err) throw err
58+
})
59+
})
60+
})
61+
}
62+
63+
function clear () {
64+
if (totalDeletes >= options.n) return report(Date.now() - startTime)
65+
66+
const start = process.hrtime()
67+
db.clear({ gte: generator.key(totalDeletes), limit: window }, function (err) {
68+
if (err) throw err
69+
70+
const duration = process.hrtime(start)
71+
const nano = (duration[0] * 1e9) + duration[1]
72+
73+
timesAccum += nano / window
74+
totalDeletes += window
75+
76+
if (totalDeletes % progressWindow === 0) {
77+
console.log('' + inProgress, totalDeletes,
78+
Math.round(totalDeletes / options.n * 100) + '%')
79+
}
80+
81+
elapsed = Date.now() - startTime
82+
stream.write(
83+
elapsed +
84+
',' + totalDeletes +
85+
',' + totalBytes +
86+
',' + (timesAccum / window).toFixed(3) +
87+
',' + ((totalDeletes) / (elapsed / 1e3)).toFixed(3) +
88+
'\n')
89+
timesAccum = 0
90+
clear()
91+
})
92+
}
93+
94+
clear()
95+
}
96+
97+
factory(function (err, db) {
98+
if (err) throw err
99+
100+
let entries = 0
101+
102+
function loop (err) {
103+
if (err) throw err
104+
105+
console.log('Prep: wrote %d of %d entries', entries, options.n)
106+
if (entries >= options.n) return setTimeout(() => start(db), 500)
107+
108+
const batch = db.batch()
109+
110+
for (let i = 0; i < 1e3 && entries < options.n; i++) {
111+
const key = generator.key(entries++)
112+
const value = generator.value()
113+
114+
batch.put(key, value)
115+
}
116+
117+
batch.write(loop)
118+
}
119+
120+
loop()
121+
})
122+
}

benchmarks/clear.plot.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict'
2+
3+
const e = require('../lib/escape-gnuplot-string')
4+
5+
module.exports = function (title, description, results) {
6+
const durations = results.map(function (res, i) {
7+
const file = res.csvFile
8+
const title = res.id(results)
9+
10+
return `'${e(file)}' using ($1/1000):($4) title '${e(title)}' ls ${i + 1} axes x1y1`
11+
})
12+
13+
const throughputs = results.map(function (res, i) {
14+
const file = res.csvFile
15+
const title = res.id(results)
16+
17+
return `'${e(file)}' using ($1/1000):($5) w lines title '${e(title)}' ls ${i + 1} axes x1y1`
18+
})
19+
20+
return `
21+
reset
22+
set terminal pngcairo truecolor enhanced font "Ubuntu Mono,10" size 1920, 1080 background rgb "#1b1b1b"
23+
set datafile separator ','
24+
25+
set autoscale y
26+
set ytics mirror
27+
set tics in
28+
set xlabel "Time (seconds)" tc rgb "#999999"
29+
30+
set key outside tc rgb "#999999"
31+
set border lc rgb "#999999"
32+
33+
# To plot more than 5 files, add more line styles
34+
set style line 1 lt 7 ps 0.8 lc rgb "#00FFFF"
35+
set style line 2 lt 7 ps 0.8 lc rgb "#D84797"
36+
set style line 3 lt 7 ps 0.8 lc rgb "#23CE6B"
37+
set style line 4 lt 7 ps 0.8 lc rgb "#F5B700"
38+
set style line 5 lt 7 ps 0.8 lc rgb "#731DD8"
39+
40+
set multiplot layout 2,1
41+
set lmargin at screen 0.1
42+
43+
set title '${e(title)}' tc rgb "#cccccc" offset 0,0.1 font "Ubuntu Mono,12"
44+
set label 1 '${e(description)}' tc rgb "#999999" at graph 0.5,1.10 center front
45+
set ylabel 'SMA ns/read' tc rgb "#999999"
46+
set logscale y
47+
plot ${durations.join(', ')}
48+
49+
set title ""
50+
set label 1 ""
51+
set ylabel 'CMA Throughput entries/s' tc rgb "#999999"
52+
set nologscale y
53+
plot ${throughputs.join(', ')}
54+
unset multiplot`
55+
}

benchmarks/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22

33
exports.put = require('./put')
44
exports['batch-put'] = require('./batch-put')
5+
exports.iterate = require('./iterate')
6+
exports.clear = require('./clear')
57
exports['self-distribution'] = require('./self-distribution')

benchmarks/iterate.js

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
'use strict'
2+
3+
const keyspace = require('keyspace')
4+
const ldu = require('../lib/level-du')
5+
const window = 1000
6+
const progressWindow = window * 100
7+
8+
exports.defaults = {
9+
benchmark: {
10+
n: 1e6,
11+
concurrency: 1,
12+
valueSize: 100,
13+
buffers: false,
14+
keys: 'random',
15+
values: 'random',
16+
seed: 'seed'
17+
}
18+
}
19+
20+
exports.plot = require('./iterate.plot')
21+
22+
exports.run = function (factory, stream, options) {
23+
if (options.n < window) {
24+
throw new RangeError('The "n" option must be >= ' + window)
25+
} else if (options.n % window !== 0) {
26+
throw new Error('The "n" option must be a multiple of ' + window)
27+
}
28+
29+
const generator = keyspace(options.n, options)
30+
31+
stream.write('Elapsed (ms), Entries, Bytes, ns/read, CMA MB/s\n')
32+
33+
function start (db) {
34+
const startTime = Date.now()
35+
36+
let inProgress = 0
37+
let totalReads = 0
38+
let totalBytes = 0
39+
let timesAccum = 0
40+
let elapsed
41+
42+
function report () {
43+
console.log(
44+
'Iterated', options.n, 'entries in',
45+
Math.floor((Date.now() - startTime) / 1e3) + 's,',
46+
(Math.floor((totalBytes / 1048576) * 100) / 100) + 'MB'
47+
)
48+
49+
stream.end()
50+
51+
db.close(function (err) {
52+
if (err) throw err
53+
54+
ldu(db, function (err, size) {
55+
if (err) throw err
56+
if (size) console.log('Database size:', Math.floor(size / 1024 / 1024) + 'M')
57+
})
58+
})
59+
}
60+
61+
function iterate () {
62+
if (totalReads >= options.n) return report(Date.now() - startTime)
63+
if (inProgress >= options.concurrency) return
64+
65+
inProgress++
66+
67+
const it = db.iterator({
68+
keyAsBuffer: options.buffers,
69+
valueAsBuffer: options.buffers
70+
})
71+
72+
function loop() {
73+
if (totalReads >= options.n) return end()
74+
const start = process.hrtime()
75+
76+
it.next(function (err, key, value) {
77+
if (err) throw err
78+
if (key === undefined && value === undefined) return end()
79+
80+
const duration = process.hrtime(start)
81+
const nano = (duration[0] * 1e9) + duration[1]
82+
83+
timesAccum += nano
84+
totalBytes += Buffer.byteLength(key) + Buffer.byteLength(value)
85+
totalReads++
86+
87+
if (totalReads % progressWindow === 0) {
88+
console.log('' + inProgress, totalReads,
89+
Math.round(totalReads / options.n * 100) + '%')
90+
}
91+
92+
if (totalReads % window === 0) {
93+
elapsed = Date.now() - startTime
94+
stream.write(
95+
elapsed +
96+
',' + totalReads +
97+
',' + totalBytes +
98+
',' + (timesAccum / window).toFixed(3) +
99+
',' + ((totalBytes / 1048576) / (elapsed / 1e3)).toFixed(3) +
100+
'\n')
101+
timesAccum = 0
102+
}
103+
104+
loop()
105+
})
106+
}
107+
108+
function end () {
109+
it.end(function (err) {
110+
if (err) throw err
111+
inProgress--
112+
process.nextTick(iterate)
113+
})
114+
}
115+
116+
loop()
117+
}
118+
119+
for (let i = 0; i < options.concurrency; i++) iterate()
120+
}
121+
122+
factory(function (err, db) {
123+
if (err) throw err
124+
125+
let entries = 0
126+
127+
function loop (err) {
128+
if (err) throw err
129+
130+
console.log('Prep: wrote %d of %d entries', entries, options.n)
131+
if (entries >= options.n) return setTimeout(() => start(db), 500)
132+
133+
const batch = db.batch()
134+
135+
for (let i = 0; i < 1e3 && entries < options.n; i++) {
136+
const key = generator.key(entries++)
137+
const value = generator.value()
138+
139+
batch.put(key, value)
140+
}
141+
142+
batch.write(loop)
143+
}
144+
145+
loop()
146+
})
147+
}

benchmarks/iterate.plot.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict'
2+
3+
const e = require('../lib/escape-gnuplot-string')
4+
5+
module.exports = function (title, description, results) {
6+
const durations = results.map(function (res, i) {
7+
const file = res.csvFile
8+
const title = res.id(results)
9+
10+
return `'${e(file)}' using ($1/1000):($4) title '${e(title)}' ls ${i + 1} axes x1y1`
11+
})
12+
13+
const throughputs = results.map(function (res, i) {
14+
const file = res.csvFile
15+
const title = res.id(results)
16+
17+
return `'${e(file)}' using ($1/1000):($5) w lines title '${e(title)}' ls ${i + 1} axes x1y1`
18+
})
19+
20+
return `
21+
reset
22+
set terminal pngcairo truecolor enhanced font "Ubuntu Mono,10" size 1920, 1080 background rgb "#1b1b1b"
23+
set datafile separator ','
24+
25+
set autoscale y
26+
set ytics mirror
27+
set tics in
28+
set xlabel "Time (seconds)" tc rgb "#999999"
29+
30+
set key outside tc rgb "#999999"
31+
set border lc rgb "#999999"
32+
33+
# To plot more than 5 files, add more line styles
34+
set style line 1 lt 7 ps 0.8 lc rgb "#00FFFF"
35+
set style line 2 lt 7 ps 0.8 lc rgb "#D84797"
36+
set style line 3 lt 7 ps 0.8 lc rgb "#23CE6B"
37+
set style line 4 lt 7 ps 0.8 lc rgb "#F5B700"
38+
set style line 5 lt 7 ps 0.8 lc rgb "#731DD8"
39+
40+
set multiplot layout 2,1
41+
set lmargin at screen 0.1
42+
43+
set title '${e(title)}' tc rgb "#cccccc" offset 0,0.1 font "Ubuntu Mono,12"
44+
set label 1 '${e(description)}' tc rgb "#999999" at graph 0.5,1.10 center front
45+
set ylabel 'ns/read' tc rgb "#999999"
46+
set logscale y
47+
plot ${durations.join(', ')}
48+
49+
set title ""
50+
set label 1 ""
51+
set ylabel 'CMA Throughput MB/s' tc rgb "#999999"
52+
set nologscale y
53+
plot ${throughputs.join(', ')}
54+
unset multiplot`
55+
}

0 commit comments

Comments
 (0)