Rewrite benchmark tests

feat/remove-native-modules-imports
Timothée Rebours 10 months ago
parent 792eecd1a1
commit f906b0082e
  1. 287
      benchmarks/commonUtilities.js
  2. 50
      benchmarks/ensureIndex.js
  3. 27
      benchmarks/find.js
  4. 28
      benchmarks/findOne.js
  5. 27
      benchmarks/findWithIn.js
  6. 32
      benchmarks/insert.js
  7. 35
      benchmarks/loadDatabase.js
  8. 92
      benchmarks/profiler.js
  9. 35
      benchmarks/remove.js
  10. 37
      benchmarks/update.js
  11. 292
      test/benchmark.test.js

@ -1,287 +0,0 @@
/**
* Functions that are used in several benchmark tests
*/
const fs = require('fs')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
const { callbackify } = require('util')
let executeAsap
try {
executeAsap = setImmediate
} catch (e) {
executeAsap = process.nextTick
}
/**
* Configure the benchmark
*/
module.exports.getConfiguration = function (benchDb) {
const program = require('commander')
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Use an index')
.option('-m --in-memory', 'Test with an in-memory only store')
.parse(process.argv)
const n = program.number || 10000
console.log('----------------------------')
console.log('Test with ' + n + ' documents')
console.log(program.withIndex ? 'Use an index' : 'Don\'t use an index')
console.log(program.inMemory ? 'Use an in-memory datastore' : 'Use a persistent datastore')
console.log('----------------------------')
const d = new Datastore({
filename: benchDb,
inMemoryOnly: program.inMemory
})
return { n, d, program }
}
/**
* Ensure the workspace stat and the db datafile is empty
*/
module.exports.prepareDb = function (filename, cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(filename, function () {
fs.access(filename, fs.constants.FS_OK, function (err) {
if (!err) {
fs.unlink(filename, cb)
} else { return cb() }
})
})
}
/**
* Return an array with the numbers from 0 to n-1, in a random order
* Uses Fisher Yates algorithm
* Useful to get fair tests
*/
function getRandomArray (n) {
const res = []
let i
let j
let temp
for (i = 0; i < n; i += 1) { res[i] = i }
for (i = n - 1; i >= 1; i -= 1) {
j = Math.floor((i + 1) * Math.random())
temp = res[i]
res[i] = res[j]
res[j] = temp
}
return res
}
module.exports.getRandomArray = getRandomArray
/**
* Insert a certain number of documents for testing
*/
module.exports.insertDocs = function (d, n, profiler, cb) {
const order = getRandomArray(n)
profiler.step('Begin inserting ' + n + ' docs')
function runFrom (i) {
if (i === n) { // Finished
const opsPerSecond = Math.floor(1000 * n / profiler.elapsedSinceLastStep())
console.log('===== RESULT (insert) ===== ' + opsPerSecond + ' ops/s')
profiler.step('Finished inserting ' + n + ' docs')
profiler.insertOpsPerSecond = opsPerSecond
return cb()
}
// eslint-disable-next-line n/handle-callback-err
d.insert({ docNumber: order[i] }, function (err) {
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}
/**
* Find documents with find
*/
module.exports.findDocs = function (d, n, profiler, cb) {
const order = getRandomArray(n)
profiler.step('Finding ' + n + ' documents')
function runFrom (i) {
if (i === n) { // Finished
console.log('===== RESULT (find) ===== ' + Math.floor(1000 * n / profiler.elapsedSinceLastStep()) + ' ops/s')
profiler.step('Finished finding ' + n + ' docs')
return cb()
}
// eslint-disable-next-line n/handle-callback-err
d.find({ docNumber: order[i] }, function (err, docs) {
if (docs.length !== 1 || docs[0].docNumber !== order[i]) { return cb(new Error('One find didnt work')) }
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}
/**
* Find documents with find and the $in operator
*/
module.exports.findDocsWithIn = function (d, n, profiler, cb) {
const ins = []
const arraySize = Math.min(10, n)
// Preparing all the $in arrays, will take some time
for (let i = 0; i < n; i += 1) {
ins[i] = []
for (let j = 0; j < arraySize; j += 1) {
ins[i].push((i + j) % n)
}
}
profiler.step('Finding ' + n + ' documents WITH $IN OPERATOR')
function runFrom (i) {
if (i === n) { // Finished
console.log('===== RESULT (find with in selector) ===== ' + Math.floor(1000 * n / profiler.elapsedSinceLastStep()) + ' ops/s')
profiler.step('Finished finding ' + n + ' docs')
return cb()
}
// eslint-disable-next-line n/handle-callback-err
d.find({ docNumber: { $in: ins[i] } }, function (err, docs) {
if (docs.length !== arraySize) { return cb(new Error('One find didnt work')) }
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}
/**
* Find documents with findOne
*/
module.exports.findOneDocs = function (d, n, profiler, cb) {
const order = getRandomArray(n)
profiler.step('FindingOne ' + n + ' documents')
function runFrom (i) {
if (i === n) { // Finished
console.log('===== RESULT (findOne) ===== ' + Math.floor(1000 * n / profiler.elapsedSinceLastStep()) + ' ops/s')
profiler.step('Finished finding ' + n + ' docs')
return cb()
}
// eslint-disable-next-line n/handle-callback-err
d.findOne({ docNumber: order[i] }, function (err, doc) {
if (!doc || doc.docNumber !== order[i]) { return cb(new Error('One find didnt work')) }
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}
/**
* Update documents
* options is the same as the options object for update
*/
module.exports.updateDocs = function (options, d, n, profiler, cb) {
const order = getRandomArray(n)
profiler.step('Updating ' + n + ' documents')
function runFrom (i) {
if (i === n) { // Finished
console.log('===== RESULT (update) ===== ' + Math.floor(1000 * n / profiler.elapsedSinceLastStep()) + ' ops/s')
profiler.step('Finished updating ' + n + ' docs')
return cb()
}
// Will not actually modify the document but will take the same time
d.update({ docNumber: order[i] }, { docNumber: order[i] }, options, function (err, nr) {
if (err) { return cb(err) }
if (nr !== 1) { return cb(new Error('One update didnt work')) }
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}
/**
* Remove documents
* options is the same as the options object for update
*/
module.exports.removeDocs = function (options, d, n, profiler, cb) {
const order = getRandomArray(n)
profiler.step('Removing ' + n + ' documents')
function runFrom (i) {
if (i === n) { // Finished
// opsPerSecond corresponds to 1 insert + 1 remove, needed to keep collection size at 10,000
// We need to subtract the time taken by one insert to get the time actually taken by one remove
const opsPerSecond = Math.floor(1000 * n / profiler.elapsedSinceLastStep())
const removeOpsPerSecond = Math.floor(1 / ((1 / opsPerSecond) - (1 / profiler.insertOpsPerSecond)))
console.log('===== RESULT (remove) ===== ' + removeOpsPerSecond + ' ops/s')
profiler.step('Finished removing ' + n + ' docs')
return cb()
}
d.remove({ docNumber: order[i] }, options, function (err, nr) {
if (err) { return cb(err) }
if (nr !== 1) { return cb(new Error('One remove didnt work')) }
// eslint-disable-next-line n/handle-callback-err
d.insert({ docNumber: order[i] }, function (err) { // We need to reinsert the doc so that we keep the collection's size at n
// So actually we're calculating the average time taken by one insert + one remove
executeAsap(function () {
runFrom(i + 1)
})
})
})
}
runFrom(0)
}
/**
* Load database
*/
module.exports.loadDatabase = function (d, n, profiler, cb) {
profiler.step('Loading the database ' + n + ' times')
function runFrom (i) {
if (i === n) { // Finished
console.log('===== RESULT ===== ' + Math.floor(1000 * n / profiler.elapsedSinceLastStep()) + ' ops/s')
profiler.step('Finished loading a database' + n + ' times')
return cb()
}
// eslint-disable-next-line n/handle-callback-err
d.loadDatabase(function (err) {
executeAsap(function () {
runFrom(i + 1)
})
})
}
runFrom(0)
}

@ -1,50 +0,0 @@
const program = require('commander')
const { apply, waterfall } = require('../test/utils.test.js')
const Datastore = require('../lib/datastore')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const profiler = new Profiler('INSERT BENCH')
const benchDb = 'workspace/insert.bench.db'
const d = new Datastore(benchDb)
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv)
const n = program.number || 10000
console.log('----------------------------')
console.log('Test with ' + n + ' documents')
console.log('----------------------------')
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
function (cb) {
let i
profiler.step('Begin calling ensureIndex ' + n + ' times')
for (i = 0; i < n; i += 1) {
d.ensureIndex({ fieldName: 'docNumber' })
delete d.indexes.docNumber
}
console.log('Average time for one ensureIndex: ' + (profiler.elapsedSinceLastStep() / n) + 'ms')
profiler.step('Finished calling ensureIndex ' + n + ' times')
cb()
}
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,27 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const profiler = new Profiler('FIND BENCH')
const benchDb = 'workspace/find.bench.db'
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
const n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
apply(commonUtilities.findDocs, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,28 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/findOne.bench.db'
const profiler = new Profiler('FINDONE BENCH')
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
const n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
function (cb) { setTimeout(function () { cb() }, 500) },
apply(commonUtilities.findOneDocs, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,27 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/find.bench.db'
const profiler = new Profiler('FIND BENCH')
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
const n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
apply(commonUtilities.findDocsWithIn, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,32 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/insert.bench.db'
const profiler = new Profiler('INSERT BENCH')
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
let n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) {
d.ensureIndex({ fieldName: 'docNumber' })
n = 2 * n // We will actually insert twice as many documents
// because the index is slower when the collection is already
// big. So the result given by the algorithm will be a bit worse than
// actual performance
}
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,35 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const program = require('commander')
const Datastore = require('../lib/datastore')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/loaddb.bench.db'
const profiler = new Profiler('LOADDB BENCH')
const d = new Datastore(benchDb)
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv)
const n = program.number || 10000
console.log('----------------------------')
console.log('Test with ' + n + ' documents')
console.log(program.withIndex ? 'Use an index' : "Don't use an index")
console.log('----------------------------')
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(cb)
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
apply(commonUtilities.loadDatabase, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,92 +0,0 @@
const util = require('util')
function formatTime (time, precision) {
// If we're dealing with ms, round up to seconds when time is at least 1 second
if (time > 1000 && precision === 'ms') {
return (Math.floor(time / 100) / 10) + ' s'
} else {
return time.toFixed(3) + ' ' + precision
}
}
// get time in ns
function getTime () {
const t = process.hrtime()
return (t[0] * 1e9 + t[1])
}
/**
* Create a profiler with name testName to monitor the execution time of a route
* The profiler has two arguments: a step msg and an optional reset for the internal timer
* It will display the execution time per step and total from latest rest
*
* Optional logToConsole flag, which defaults to true, causes steps to be printed to console.
* otherwise, they can be accessed from Profiler.steps array.
*/
function Profiler (name, logToConsole, precision) {
this.name = name
this.steps = []
this.sinceBeginning = null
this.lastStep = null
this.logToConsole = typeof (logToConsole) === 'undefined' ? true : logToConsole
this.precision = typeof (precision) === 'undefined' ? 'ms' : precision
this.divisor = 1
if (this.precision === 'ms') this.divisor = 1e6
}
Profiler.prototype.beginProfiling = function () {
if (this.logToConsole) { console.log(this.name + ' - Begin profiling') }
this.resetTimers()
}
Profiler.prototype.resetTimers = function () {
this.sinceBeginning = getTime()
this.lastStep = getTime()
this.steps.push(['BEGIN_TIMER', this.lastStep])
}
Profiler.prototype.elapsedSinceBeginning = function () {
return (getTime() - this.sinceBeginning) / this.divisor
}
Profiler.prototype.elapsedSinceLastStep = function () {
return (getTime() - this.lastStep) / this.divisor
}
// Return the deltas between steps, in nanoseconds
Profiler.prototype.getSteps = function () {
const divisor = this.divisor
return this.steps.map(function (curr, index, arr) {
if (index === 0) return undefined
const delta = (curr[1] - arr[index - 1][1])
return [curr[0], (delta / divisor)]
}).slice(1)
}
Profiler.prototype.step = function (msg) {
if (!this.sinceBeginning || !this.lastStep) {
console.log(util.format(
'%s - %s - You must call beginProfiling before registering steps',
this.name,
msg
))
return
}
if (this.logToConsole) {
console.log(util.format('%s - %s - %s (total: %s)',
this.name,
msg,
formatTime(this.elapsedSinceLastStep(), this.precision),
formatTime(this.elapsedSinceBeginning(), this.precision)
))
}
this.lastStep = getTime()
this.steps.push([msg, this.lastStep])
}
module.exports = Profiler

@ -1,35 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/remove.bench.db'
const profiler = new Profiler('REMOVE BENCH')
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
const n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
// Test with remove only one document
function (cb) { profiler.step('MULTI: FALSE'); return cb() },
apply(commonUtilities.removeDocs, { multi: false }, d, n, profiler),
// Test with multiple documents
function (cb) { d.remove({}, { multi: true }, function () { return cb() }) },
apply(commonUtilities.insertDocs, d, n, profiler),
function (cb) { profiler.step('MULTI: TRUE'); return cb() },
apply(commonUtilities.removeDocs, { multi: true }, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -1,37 +0,0 @@
const { apply, waterfall } = require('../test/utils.test.js')
const commonUtilities = require('./commonUtilities')
const Profiler = require('./profiler')
const benchDb = 'workspace/update.bench.db'
const profiler = new Profiler('UPDATE BENCH')
const config = commonUtilities.getConfiguration(benchDb)
const d = config.d
const n = config.n
waterfall([
apply(commonUtilities.prepareDb, benchDb),
function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err) }
if (config.program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }) }
cb()
})
},
function (cb) { profiler.beginProfiling(); return cb() },
apply(commonUtilities.insertDocs, d, n, profiler),
// Test with update only one document
function (cb) { profiler.step('MULTI: FALSE'); return cb() },
apply(commonUtilities.updateDocs, { multi: false }, d, n, profiler),
// Test with multiple documents
// eslint-disable-next-line n/handle-callback-err
function (cb) { d.remove({}, { multi: true }, function (err) { return cb() }) },
apply(commonUtilities.insertDocs, d, n, profiler),
function (cb) { profiler.step('MULTI: TRUE'); return cb() },
apply(commonUtilities.updateDocs, { multi: true }, d, n, profiler)
], function (err) {
profiler.step('Benchmark finished')
if (err) { return console.log('An error was encountered: ', err) }
})

@ -0,0 +1,292 @@
import { promisify } from 'util'
import { performance } from 'node:perf_hooks'
import Persistence from '../src/persistence.js'
import { access, unlink, constants } from 'fs/promises'
import Datastore from '../src/datastore.js'
const getRandomArray = n => {
const res = []
let i
let j
let temp
for (i = 0; i < n; i += 1) { res[i] = i }
for (i = n - 1; i >= 1; i -= 1) {
j = Math.floor((i + 1) * Math.random())
temp = res[i]
res[i] = res[j]
res[j] = temp
}
return res
}
const insertDocs = async (d, n) => {
const order = getRandomArray(n)
for (let i = 0; i <= n; i++) {
await d.insertAsync({ docNumber: order[i] })
await promisify(process.nextTick)()
}
}
const measure = async (name, n, cb) => {
performance.mark(`${name} start`)
for (let i = 0; i < n; i += 1) {
await cb(i)
}
performance.mark(`${name} end`)
const { duration } = performance.measure(`${name} average duration for ${n} operations`, `${name} start`, `${name} end`)
const opsPerSecond = Math.floor(1000 * n / duration)
console.log(`===== RESULT (${name}) ===== ${opsPerSecond} ops/s ===== ${Math.floor(duration / n * 1000) / 1000}ms/execution`)
}
describe('Performance tests without index', function () {
const n = 1000
const benchDb = 'workspace/bench.db'
let d
before(function () {
if (!process.argv.includes('--benchmark')) this.skip()
else this.timeout(60000)
})
beforeEach('Prepare database', async () => {
try {
await access(benchDb, constants.F_OK)
await unlink(benchDb)
} catch {}
await Persistence.ensureParentDirectoryExistsAsync(benchDb)
d = new Datastore({ filename: benchDb })
await d.loadDatabaseAsync()
})
afterEach('Clean database', async () => {
try {
await d.this.executor.queue.guardian
d = null
await access(benchDb, constants.F_OK)
await unlink(benchDb)
} catch {}
})
it('ensureIndex', async () => {
await insertDocs(d, n)
await measure('ensureIndex', n, async (i) => {
d.ensureIndexAsync({ fieldName: 'docNumber' })
delete d.indexes.docNumber
})
})
it('find', async () => {
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('find', n, async (i) => {
const docs = await d.findAsync({ docNumber: order[i] })
if (docs.length !== 1 || docs[0].docNumber !== order[i]) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('findOne', async () => {
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('findOne', n, async (i) => {
const doc = await d.findOneAsync({ docNumber: order[i] })
if (doc == null || doc.docNumber !== order[i]) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('find with $in', async () => {
await insertDocs(d, n)
const ins = []
const arraySize = Math.min(10, n)
// Preparing all the $in arrays, will take some time
for (let i = 0; i < n; i += 1) {
ins[i] = []
for (let j = 0; j < arraySize; j += 1) {
ins[i].push((i + j) % n)
}
}
await measure('find with $in', n, async (i) => {
const docs = await d.findAsync({ docNumber: { $in: ins[i] } })
if (docs.length !== arraySize) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('insert docs', async () => {
const order = getRandomArray(n)
await measure('insert docs', n, async (i) => {
await d.insertAsync({ docNumber: order[i] })
await promisify(process.nextTick)()
})
})
it('load database', async () => {
await insertDocs(d, n)
await measure('load database', n, async (i) => {
await d.loadDatabaseAsync()
})
})
it('Insert and remove one', async () => {
// TODO measure only remove
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one', n, async (i) => {
const nr = await d.removeAsync({ docNumber: order[i] }, { multi: false })
if (nr !== 1) throw new Error('One remove didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Insert and remove one with multi option', async () => {
// TODO measure only remove
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option', n, async (i) => {
const nr = await d.removeAsync({ docNumber: order[i] }, { multi: true })
if (nr !== 1) throw new Error('One remove didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Update', async () => {
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option', n, async (i) => {
const { numAffected } = await d.updateAsync({ docNumber: order[i] }, { docNumber: order[i] }, { multi: false })
if (numAffected !== 1) throw new Error('One update didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Update with multi option', async () => {
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option', n, async (i) => {
const { numAffected } = await d.updateAsync({ docNumber: order[i] }, { docNumber: order[i] }, { multi: true })
if (numAffected !== 1) throw new Error('One update didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('find with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('find with index', n, async (i) => {
const docs = await d.findAsync({ docNumber: order[i] })
if (docs.length !== 1 || docs[0].docNumber !== order[i]) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('findOne with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('findOne with index', n, async (i) => {
const doc = await d.findOneAsync({ docNumber: order[i] })
if (doc == null || doc.docNumber !== order[i]) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('find with $in with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const ins = []
const arraySize = Math.min(10, n)
// Preparing all the $in arrays, will take some time
for (let i = 0; i < n; i += 1) {
ins[i] = []
for (let j = 0; j < arraySize; j += 1) {
ins[i].push((i + j) % n)
}
}
await measure('find with $in with index', n, async (i) => {
const docs = await d.findAsync({ docNumber: { $in: ins[i] } })
if (docs.length !== arraySize) throw new Error('One find didnt work')
await promisify(process.nextTick)()
})
})
it('insert docs with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
const order = getRandomArray(n)
await measure('insert docs with index', n, async (i) => {
await d.insertAsync({ docNumber: order[i] })
await promisify(process.nextTick)()
})
})
it('load database with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
await measure('load database with index', n, async (i) => {
await d.loadDatabaseAsync()
})
})
it('Insert and remove one with index', async () => {
// TODO measure only remove
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with index', n, async (i) => {
const nr = await d.removeAsync({ docNumber: order[i] }, { multi: false })
if (nr !== 1) throw new Error('One remove didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Insert and remove one with multi option with index', async () => {
// TODO measure only remove
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option with index', n, async (i) => {
const nr = await d.removeAsync({ docNumber: order[i] }, { multi: true })
if (nr !== 1) throw new Error('One remove didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Update with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option with index', n, async (i) => {
const { numAffected } = await d.updateAsync({ docNumber: order[i] }, { docNumber: order[i] }, { multi: false })
if (numAffected !== 1) throw new Error('One update didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
it('Update with multi option with index', async () => {
await d.ensureIndexAsync({ fieldName: 'docNumber' })
await insertDocs(d, n)
const order = getRandomArray(n)
await measure('insert and remove one with multi option with index', n, async (i) => {
const { numAffected } = await d.updateAsync({ docNumber: order[i] }, { docNumber: order[i] }, { multi: true })
if (numAffected !== 1) throw new Error('One update didnt work')
await d.insertAsync({ docNumber: order[i] })
})
})
})
Loading…
Cancel
Save