diff --git a/README.md b/README.md index 70a4ac3..c3d523f 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Yet to document. ### `put` -Perform concurrent `put()` operations on random or sequential string keys and values. Records the Simple Moving Average (SMA) of the duration of the last 1000 writes, as well as the Cumulative Moving Average (CMA) of the throughput in MB/s. Options: +Perform concurrent `put()` operations. Records the Simple Moving Average (SMA) of the duration of the last 1000 writes, as well as the Cumulative Moving Average (CMA) of the throughput in MB/s. Options: - `-n`: amount of operations, default 1e6 - `--concurrency`: default 4 @@ -143,13 +143,12 @@ Tips: ### `batch-put` -Same as `put`, but in batches rather than singular puts. Perform concurrent `batch()` operations on random string keys and values. Options: +Perform concurrent `batch()` operations. Same as `put`, but in batches rather than singular puts. Options: -- `-n`: amount of operations, default 1e6 -- `--batchSize`: default 1000 +- `--batchSize`: default 1000, must be a multiple of 10, maximum 1000 - `--chained`: boolean flag, default false, use chained batch - `--concurrency`: default 1 -- `--valueSize`: size of value, as a number in bytes or string with unit (e.g. `--valueSize 1kb`) +- Other options are the same as of the `put` benchmark, see above. ### `self-distribution` diff --git a/benchmarks/batch-put.js b/benchmarks/batch-put.js index 8ba4f8e..6306e97 100644 --- a/benchmarks/batch-put.js +++ b/benchmarks/batch-put.js @@ -1,8 +1,9 @@ 'use strict' -const crypto = require('crypto') +const keyspace = require('keyspace') const ldu = require('../lib/level-du') -const keyTmpl = '0000000000000000' +const window = 1000 +const progressWindow = window * 100 exports.defaults = { benchmark: { @@ -10,21 +11,29 @@ exports.defaults = { batchSize: 1e3, concurrency: 1, valueSize: 100, - chained: false + chained: false, + keys: 'random', + values: 'random', + seed: 'seed' } } -exports.plot = require('./batch-put.plot') +exports.plot = require('./put.plot') exports.run = function (factory, stream, options) { - stream.write('Elapsed (ms), Entries, Bytes, Last 1000 Avg Time, MB/s\n') + if (options.batchSize <= 0 || options.batchSize > window) { + throw new RangeError('The "batchSize" option must be > 0 <= ' + window) + } else if (options.batchSize % 10 !== 0) { + throw new Error('The "batchSize" option must be a multiple of 10') + } else if (options.batchSize > options.n) { + throw new RangeError('The "batchSize" option must be <= n') + } else if (options.n % options.batchSize !== 0) { + throw new Error('The "n" option must be a multiple of "batchSize"') + } - function make16CharPaddedKey () { - const r = Math.floor(Math.random() * options.n) - const k = keyTmpl + r + const generator = keyspace(options.n, options) - return k.substr(k.length - 16) - } + stream.write('Elapsed (ms), Entries, Bytes, SMA ms/write, CMA MB/s\n') function start (db) { const startTime = Date.now() @@ -39,7 +48,7 @@ exports.run = function (factory, stream, options) { function report () { console.log( 'Wrote', options.n, 'entries in', - Math.floor((Date.now() - startTime) / 1000) + 's,', + Math.floor((Date.now() - startTime) / 1e3) + 's,', (Math.floor((totalBytes / 1048576) * 100) / 100) + 'MB' ) @@ -61,20 +70,19 @@ exports.run = function (factory, stream, options) { inProgress++ - if (totalWrites % 100000 === 0) { + if (totalWrites % progressWindow === 0) { console.log('' + inProgress, totalWrites, Math.round(totalWrites / options.n * 100) + '%') } - // TODO: batchSize should be a multiple of 10 - if (totalWrites % 1000 === 0) { + if (totalWrites % window === 0) { elapsed = Date.now() - startTime stream.write( elapsed + ',' + totalWrites + ',' + totalBytes + - ',' + Math.floor(timesAccum / 1000) + - ',' + (Math.floor(((totalBytes / 1048576) / (elapsed / 1000)) * 100) / 100) + + ',' + (timesAccum / window / 1e6).toFixed(3) + + ',' + ((totalBytes / 1048576) / (elapsed / 1e3)).toFixed(3) + '\n') timesAccum = 0 } @@ -85,10 +93,11 @@ exports.run = function (factory, stream, options) { const batch = db.batch() for (let i = 0; i < batchSize; i++) { - // TODO: see comment in write.js - const key = make16CharPaddedKey() - const value = crypto.randomBytes(options.valueSize).toString('hex') + const key = generator.key(totalWrites++) + const value = generator.value() + // TODO: see comment in put.js + totalBytes += Buffer.byteLength(key) + Buffer.byteLength(value) batch.put(key, value) } @@ -98,10 +107,11 @@ exports.run = function (factory, stream, options) { const ops = new Array(batchSize) for (let i = 0; i < batchSize; i++) { - // TODO: see comment in write.js - const key = make16CharPaddedKey() - const value = crypto.randomBytes(options.valueSize).toString('hex') + const key = generator.key(totalWrites++) + const value = generator.value() + // TODO: see comment in put.js + totalBytes += Buffer.byteLength(key) + Buffer.byteLength(value) ops[i] = { type: 'put', key, value } } @@ -115,8 +125,6 @@ exports.run = function (factory, stream, options) { const duration = process.hrtime(start) const nano = (duration[0] * 1e9) + duration[1] - totalBytes += (keyTmpl.length + options.valueSize) * batchSize - totalWrites += batchSize timesAccum += nano inProgress-- diff --git a/benchmarks/batch-put.plot.js b/benchmarks/batch-put.plot.js deleted file mode 100644 index b77ca2f..0000000 --- a/benchmarks/batch-put.plot.js +++ /dev/null @@ -1,55 +0,0 @@ -'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/1000000) 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.7 font "Ubuntu Mono,12" - set label 1 '${e(description)}' tc rgb "#999999" at graph 0.5,1.10 center front - set ylabel 'Milliseconds/write' tc rgb "#999999" - set logscale y - plot ${durations.join(', ')} - - set title "" - set label 1 "" - set ylabel 'Throughput MB/s' tc rgb "#999999" - set nologscale y - plot ${throughputs.join(', ')} - unset multiplot` -} diff --git a/benchmarks/put.plot.js b/benchmarks/put.plot.js index 8b917a5..4980521 100644 --- a/benchmarks/put.plot.js +++ b/benchmarks/put.plot.js @@ -2,6 +2,7 @@ const e = require('../lib/escape-gnuplot-string') +// Note: also used by the batch-put benchmark. module.exports = function (title, description, results) { const durations = results.map(function (res, i) { const file = res.csvFile diff --git a/lib/meta.js b/lib/meta.js index 71d7749..0bdc68e 100644 --- a/lib/meta.js +++ b/lib/meta.js @@ -85,6 +85,7 @@ function id (meta, peers, invert, opts) { for (let k of sortKeys(Object.keys(node), ORDER)) { if (opts && opts.include && opts.include.indexOf(k) < 0) continue if (opts && opts.exclude && opts.exclude.indexOf(k) >= 0) continue + if (k === 'seed') continue const v = node[k]