-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add iterate and clear benchmarks (#29)
Undocumented for now because they're in POC stage.
- Loading branch information
Showing
5 changed files
with
381 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
'use strict' | ||
|
||
const keyspace = require('keyspace') | ||
const window = 1000 | ||
const progressWindow = window * 100 | ||
|
||
exports.defaults = { | ||
benchmark: { | ||
n: 1e6, | ||
valueSize: 100, | ||
keys: 'seq', | ||
values: 'random', | ||
seed: 'seed' | ||
} | ||
} | ||
|
||
exports.plot = require('./clear.plot') | ||
|
||
exports.run = function (factory, stream, options) { | ||
if (options.n < window) { | ||
throw new RangeError('The "n" option must be >= ' + window) | ||
} else if (options.n % window !== 0) { | ||
throw new Error('The "n" option must be a multiple of ' + window) | ||
} | ||
|
||
const generator = keyspace(options.n, options) | ||
|
||
stream.write('Elapsed (ms), Entries, Bytes, SMA ns/write, CMA entries/s\n') | ||
|
||
function start (db) { | ||
const startTime = Date.now() | ||
const inProgress = 0 // TODO: remove | ||
const totalBytes = 0 // TODO: remove. Can't know | ||
|
||
let totalDeletes = 0 | ||
let timesAccum = 0 | ||
let elapsed | ||
|
||
function report () { | ||
console.log( | ||
'Cleared', options.n, 'entries in', | ||
Math.floor((Date.now() - startTime) / 1e3) + 's' | ||
) | ||
|
||
stream.end() | ||
|
||
const it = db.iterator() | ||
|
||
it.next(function (err, key) { | ||
if (err) throw err | ||
if (key !== undefined) throw new Error('Did not clear all') | ||
|
||
it.end(function (err) { | ||
if (err) throw err | ||
|
||
db.close(function (err) { | ||
if (err) throw err | ||
}) | ||
}) | ||
}) | ||
} | ||
|
||
function clear () { | ||
if (totalDeletes >= options.n) return report(Date.now() - startTime) | ||
|
||
const start = process.hrtime() | ||
db.clear({ gte: generator.key(totalDeletes), limit: window }, function (err) { | ||
if (err) throw err | ||
|
||
const duration = process.hrtime(start) | ||
const nano = (duration[0] * 1e9) + duration[1] | ||
|
||
timesAccum += nano / window | ||
totalDeletes += window | ||
|
||
if (totalDeletes % progressWindow === 0) { | ||
console.log('' + inProgress, totalDeletes, | ||
Math.round(totalDeletes / options.n * 100) + '%') | ||
} | ||
|
||
elapsed = Date.now() - startTime | ||
stream.write( | ||
elapsed + | ||
',' + totalDeletes + | ||
',' + totalBytes + | ||
',' + (timesAccum / window).toFixed(3) + | ||
',' + ((totalDeletes) / (elapsed / 1e3)).toFixed(3) + | ||
'\n') | ||
timesAccum = 0 | ||
clear() | ||
}) | ||
} | ||
|
||
clear() | ||
} | ||
|
||
factory(function (err, db) { | ||
if (err) throw err | ||
|
||
let entries = 0 | ||
|
||
function loop (err) { | ||
if (err) throw err | ||
|
||
console.log('Prep: wrote %d of %d entries', entries, options.n) | ||
if (entries >= options.n) return setTimeout(() => start(db), 500) | ||
|
||
const batch = db.batch() | ||
|
||
for (let i = 0; i < 1e3 && entries < options.n; i++) { | ||
const key = generator.key(entries++) | ||
const value = generator.value() | ||
|
||
batch.put(key, value) | ||
} | ||
|
||
batch.write(loop) | ||
} | ||
|
||
loop() | ||
}) | ||
} |
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,55 @@ | ||
'use strict' | ||
|
||
const e = require('../lib/escape-gnuplot-string') | ||
|
||
module.exports = function (title, description, results) { | ||
const durations = results.map(function (res, i) { | ||
const file = res.csvFile | ||
const title = res.id(results) | ||
|
||
return `'${e(file)}' using ($1/1000):($4) title '${e(title)}' ls ${i + 1} axes x1y1` | ||
}) | ||
|
||
const throughputs = results.map(function (res, i) { | ||
const file = res.csvFile | ||
const title = res.id(results) | ||
|
||
return `'${e(file)}' using ($1/1000):($5) w lines title '${e(title)}' ls ${i + 1} axes x1y1` | ||
}) | ||
|
||
return ` | ||
reset | ||
set terminal pngcairo truecolor enhanced font "Ubuntu Mono,10" size 1920, 1080 background rgb "#1b1b1b" | ||
set datafile separator ',' | ||
set autoscale y | ||
set ytics mirror | ||
set tics in | ||
set xlabel "Time (seconds)" tc rgb "#999999" | ||
set key outside tc rgb "#999999" | ||
set border lc rgb "#999999" | ||
# To plot more than 5 files, add more line styles | ||
set style line 1 lt 7 ps 0.8 lc rgb "#00FFFF" | ||
set style line 2 lt 7 ps 0.8 lc rgb "#D84797" | ||
set style line 3 lt 7 ps 0.8 lc rgb "#23CE6B" | ||
set style line 4 lt 7 ps 0.8 lc rgb "#F5B700" | ||
set style line 5 lt 7 ps 0.8 lc rgb "#731DD8" | ||
set multiplot layout 2,1 | ||
set lmargin at screen 0.1 | ||
set title '${e(title)}' tc rgb "#cccccc" offset 0,0.1 font "Ubuntu Mono,12" | ||
set label 1 '${e(description)}' tc rgb "#999999" at graph 0.5,1.10 center front | ||
set ylabel 'SMA ns/read' tc rgb "#999999" | ||
set logscale y | ||
plot ${durations.join(', ')} | ||
set title "" | ||
set label 1 "" | ||
set ylabel 'CMA Throughput entries/s' tc rgb "#999999" | ||
set nologscale y | ||
plot ${throughputs.join(', ')} | ||
unset multiplot` | ||
} |
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
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,147 @@ | ||
'use strict' | ||
|
||
const keyspace = require('keyspace') | ||
const ldu = require('../lib/level-du') | ||
const window = 1000 | ||
const progressWindow = window * 100 | ||
|
||
exports.defaults = { | ||
benchmark: { | ||
n: 1e6, | ||
concurrency: 1, | ||
valueSize: 100, | ||
buffers: false, | ||
keys: 'random', | ||
values: 'random', | ||
seed: 'seed' | ||
} | ||
} | ||
|
||
exports.plot = require('./iterate.plot') | ||
|
||
exports.run = function (factory, stream, options) { | ||
if (options.n < window) { | ||
throw new RangeError('The "n" option must be >= ' + window) | ||
} else if (options.n % window !== 0) { | ||
throw new Error('The "n" option must be a multiple of ' + window) | ||
} | ||
|
||
const generator = keyspace(options.n, options) | ||
|
||
stream.write('Elapsed (ms), Entries, Bytes, ns/read, CMA MB/s\n') | ||
|
||
function start (db) { | ||
const startTime = Date.now() | ||
|
||
let inProgress = 0 | ||
let totalReads = 0 | ||
let totalBytes = 0 | ||
let timesAccum = 0 | ||
let elapsed | ||
|
||
function report () { | ||
console.log( | ||
'Iterated', options.n, 'entries in', | ||
Math.floor((Date.now() - startTime) / 1e3) + 's,', | ||
(Math.floor((totalBytes / 1048576) * 100) / 100) + 'MB' | ||
) | ||
|
||
stream.end() | ||
|
||
db.close(function (err) { | ||
if (err) throw err | ||
|
||
ldu(db, function (err, size) { | ||
if (err) throw err | ||
if (size) console.log('Database size:', Math.floor(size / 1024 / 1024) + 'M') | ||
}) | ||
}) | ||
} | ||
|
||
function iterate () { | ||
if (totalReads >= options.n) return report(Date.now() - startTime) | ||
if (inProgress >= options.concurrency) return | ||
|
||
inProgress++ | ||
|
||
const it = db.iterator({ | ||
keyAsBuffer: options.buffers, | ||
valueAsBuffer: options.buffers | ||
}) | ||
|
||
function loop () { | ||
if (totalReads >= options.n) return end() | ||
const start = process.hrtime() | ||
|
||
it.next(function (err, key, value) { | ||
if (err) throw err | ||
if (key === undefined && value === undefined) return end() | ||
|
||
const duration = process.hrtime(start) | ||
const nano = (duration[0] * 1e9) + duration[1] | ||
|
||
timesAccum += nano | ||
totalBytes += Buffer.byteLength(key) + Buffer.byteLength(value) | ||
totalReads++ | ||
|
||
if (totalReads % progressWindow === 0) { | ||
console.log('' + inProgress, totalReads, | ||
Math.round(totalReads / options.n * 100) + '%') | ||
} | ||
|
||
if (totalReads % window === 0) { | ||
elapsed = Date.now() - startTime | ||
stream.write( | ||
elapsed + | ||
',' + totalReads + | ||
',' + totalBytes + | ||
',' + (timesAccum / window).toFixed(3) + | ||
',' + ((totalBytes / 1048576) / (elapsed / 1e3)).toFixed(3) + | ||
'\n') | ||
timesAccum = 0 | ||
} | ||
|
||
loop() | ||
}) | ||
} | ||
|
||
function end () { | ||
it.end(function (err) { | ||
if (err) throw err | ||
inProgress-- | ||
process.nextTick(iterate) | ||
}) | ||
} | ||
|
||
loop() | ||
} | ||
|
||
for (let i = 0; i < options.concurrency; i++) iterate() | ||
} | ||
|
||
factory(function (err, db) { | ||
if (err) throw err | ||
|
||
let entries = 0 | ||
|
||
function loop (err) { | ||
if (err) throw err | ||
|
||
console.log('Prep: wrote %d of %d entries', entries, options.n) | ||
if (entries >= options.n) return setTimeout(() => start(db), 500) | ||
|
||
const batch = db.batch() | ||
|
||
for (let i = 0; i < 1e3 && entries < options.n; i++) { | ||
const key = generator.key(entries++) | ||
const value = generator.value() | ||
|
||
batch.put(key, value) | ||
} | ||
|
||
batch.write(loop) | ||
} | ||
|
||
loop() | ||
}) | ||
} |
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,55 @@ | ||
'use strict' | ||
|
||
const e = require('../lib/escape-gnuplot-string') | ||
|
||
module.exports = function (title, description, results) { | ||
const durations = results.map(function (res, i) { | ||
const file = res.csvFile | ||
const title = res.id(results) | ||
|
||
return `'${e(file)}' using ($1/1000):($4) title '${e(title)}' ls ${i + 1} axes x1y1` | ||
}) | ||
|
||
const throughputs = results.map(function (res, i) { | ||
const file = res.csvFile | ||
const title = res.id(results) | ||
|
||
return `'${e(file)}' using ($1/1000):($5) w lines title '${e(title)}' ls ${i + 1} axes x1y1` | ||
}) | ||
|
||
return ` | ||
reset | ||
set terminal pngcairo truecolor enhanced font "Ubuntu Mono,10" size 1920, 1080 background rgb "#1b1b1b" | ||
set datafile separator ',' | ||
set autoscale y | ||
set ytics mirror | ||
set tics in | ||
set xlabel "Time (seconds)" tc rgb "#999999" | ||
set key outside tc rgb "#999999" | ||
set border lc rgb "#999999" | ||
# To plot more than 5 files, add more line styles | ||
set style line 1 lt 7 ps 0.8 lc rgb "#00FFFF" | ||
set style line 2 lt 7 ps 0.8 lc rgb "#D84797" | ||
set style line 3 lt 7 ps 0.8 lc rgb "#23CE6B" | ||
set style line 4 lt 7 ps 0.8 lc rgb "#F5B700" | ||
set style line 5 lt 7 ps 0.8 lc rgb "#731DD8" | ||
set multiplot layout 2,1 | ||
set lmargin at screen 0.1 | ||
set title '${e(title)}' tc rgb "#cccccc" offset 0,0.1 font "Ubuntu Mono,12" | ||
set label 1 '${e(description)}' tc rgb "#999999" at graph 0.5,1.10 center front | ||
set ylabel 'ns/read' tc rgb "#999999" | ||
set logscale y | ||
plot ${durations.join(', ')} | ||
set title "" | ||
set label 1 "" | ||
set ylabel 'CMA Throughput MB/s' tc rgb "#999999" | ||
set nologscale y | ||
plot ${throughputs.join(', ')} | ||
unset multiplot` | ||
} |