diff --git a/.travis.yml b/.travis.yml
index 39dbb1f..2a8cd7b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,8 @@ env:
matrix:
include:
- - env: TO_TEST=NodeJS
+ - env: TO_TEST=leveldb
+ - env: TO_TEST=lmdb
- env: TO_TEST=ESLint
# - os: osx
# env: TO_TEST=Karma/Travis_CI/Safari
@@ -92,6 +93,7 @@ script:
- if [[ "$TO_TEST" == Karma/Travis_CI/Firefox_* ]] && [ "$KARMA_BROWSERS" = "" ]; then export KARMA_BROWSERS=Firefox TO_TEST=Karma USE_ISTANBUL=1; fi
- if [[ "$TO_TEST" == Karma/Travis_CI/* ]] && [ "$KARMA_BROWSERS" = "" ]; then export KARMA_BROWSERS=Safari TO_TEST=Karma; fi
- if [ "$TO_TEST" = "Karma" ]; then node_modules/.bin/karma start; fi
-- if [ "$TO_TEST" = "NodeJS" ]; then node_modules/.bin/jasmine; fi
+- if [ "$TO_TEST" = "leveldb" ]; then node_modules/.bin/jasmine; fi
+- if [ "$TO_TEST" = "lmdb" ]; then node_modules/.bin/jasmine --config=spec/support/lmdb-jasmine.json; fi
- if [ "$TO_TEST" = "ESLint" ]; then node_modules/.bin/eslint src/main src/test *.js && node_modules/.bin/esdoc; fi
- if [ "$USE_ISTANBUL" = "1" ]; then node_modules/.bin/codecov; fi
diff --git a/benchmark/browser/BenchmarkUi.js b/benchmark/indexeddb/BenchmarkUi.js
similarity index 100%
rename from benchmark/browser/BenchmarkUi.js
rename to benchmark/indexeddb/BenchmarkUi.js
diff --git a/benchmark/browser/BenchmarkView.js b/benchmark/indexeddb/BenchmarkView.js
similarity index 100%
rename from benchmark/browser/BenchmarkView.js
rename to benchmark/indexeddb/BenchmarkView.js
diff --git a/benchmark/browser/SelectorBar.js b/benchmark/indexeddb/SelectorBar.js
similarity index 100%
rename from benchmark/browser/SelectorBar.js
rename to benchmark/indexeddb/SelectorBar.js
diff --git a/benchmark/browser/UiComponent.js b/benchmark/indexeddb/UiComponent.js
similarity index 100%
rename from benchmark/browser/UiComponent.js
rename to benchmark/indexeddb/UiComponent.js
diff --git a/benchmark/browser/index.html b/benchmark/indexeddb/index.html
similarity index 96%
rename from benchmark/browser/index.html
rename to benchmark/indexeddb/index.html
index ba5b1c4..f4c54ef 100644
--- a/benchmark/browser/index.html
+++ b/benchmark/indexeddb/index.html
@@ -3,7 +3,7 @@
JungleDB Browser Benchmark
-
+
diff --git a/benchmark/nodejs/index.js b/benchmark/leveldb/index.js
similarity index 54%
rename from benchmark/nodejs/index.js
rename to benchmark/leveldb/index.js
index f58d137..bbcb4b8 100644
--- a/benchmark/nodejs/index.js
+++ b/benchmark/leveldb/index.js
@@ -3,6 +3,7 @@ process.on('uncaughtException', function(err){
process.exit();
});
+const JDB = require('../../dist/leveldb.js');
const BenchmarkRunner = require('../shared/BenchmarkRunner.js');
-BenchmarkRunner.runBenchmarks().then(() => console.log('\nBenchmarks finished.'));
+BenchmarkRunner.runBenchmarks(undefined, JDB).then(() => console.log('\nBenchmarks finished.'));
diff --git a/benchmark/lmdb/index.js b/benchmark/lmdb/index.js
new file mode 100644
index 0000000..7d50142
--- /dev/null
+++ b/benchmark/lmdb/index.js
@@ -0,0 +1,9 @@
+process.on('uncaughtException', function(err){
+ console.error(err.stack);
+ process.exit();
+});
+
+const JDB = require('../../dist/lmdb.js');
+const BenchmarkRunner = require('../shared/BenchmarkRunner.js');
+
+BenchmarkRunner.runBenchmarks(undefined, JDB, { maxDbSize: 1024*1024*1024 }).then(() => console.log('\nBenchmarks finished.'));
diff --git a/benchmark/shared/Benchmark.js b/benchmark/shared/Benchmark.js
index a38e2e6..568f1b6 100644
--- a/benchmark/shared/Benchmark.js
+++ b/benchmark/shared/Benchmark.js
@@ -1,5 +1,4 @@
if (typeof(require) !== 'undefined') {
- JDB = require('../../dist/node.js');
Stats = require('./Stats.js');
BenchmarkUtils = require('./BenchmarkUtils.js');
}
@@ -10,19 +9,37 @@ class Benchmark {
* @param {number} benchmarkVersion
* @param {Array.} tableNames
*/
- constructor(name, benchmarkVersion = 1, tableNames = ['default']) {
+ constructor(name, benchmarkVersion = 1, tableNames = ['default'], indices = {}) {
this.name = name;
this._databaseName = `db-${name}`;
this._tableNames = tableNames;
this._objectStores = [];
+ this._indices = indices;
this._benchmarkVersion = benchmarkVersion;
this._db = null;
+
+ this._jdbOptions = {};
+ this._jdb = null;
+ }
+
+ setJDB(customJDB, options) {
+ this._jdb = customJDB;
+ this._jdbOptions = options || {};
+ }
+
+ get jdb() {
+ return this._jdb ? this._jdb : JDB;
}
async _init() {
- this._db = new JDB.JungleDB(this._databaseName, this._benchmarkVersion);
+ this._db = new this.jdb.JungleDB(this._databaseName, this._benchmarkVersion, undefined, this._jdbOptions);
for (const tableName of this._tableNames) {
- this._objectStores.push(this._db.createObjectStore(tableName));
+ const store = this._db.createObjectStore(tableName);
+ this._objectStores.push(store);
+ if (this._indices[tableName]) {
+ const { name, keyPath } = this._indices[tableName];
+ store.createIndex(name, keyPath);
+ }
}
await this._db.connect();
}
@@ -56,7 +73,6 @@ class Benchmark {
* @returns {Promise.}
*/
async run(count = 2) {
- BenchmarkUtils.logColored(`\n\nRun benchmark ${this.description || this.name}:`);
await this._init();
const stats = [];
for (let i=0; idatabaseEntryCount || batchSize>databaseEntryCount
+ || (batchSize===1 && !sync)) { // we ignore this setting as it is the same as batchSize 1 with sync
+ throw('Illegal parameter combination.');
+ }
+ const indices = {};
+ indices[BenchmarkReadIndex.TABLE_NAME] = { name: 'index', keyPath: 'index' };
+ super(BenchmarkReadIndex.NAME, BenchmarkReadIndex.VERSION, [BenchmarkReadIndex.TABLE_NAME], indices);
+ this._databaseEntryCount = databaseEntryCount;
+ this._readCount = readCount;
+ this._entrySize = entrySize;
+ this._batchSize = batchSize;
+ this._sync = sync;
+ this._entryKeys = BenchmarkUtils.createRandomKeys(databaseEntryCount);
+ this._indexKeys = BenchmarkUtils.createRandomKeys(databaseEntryCount);
+ this.description = `${BenchmarkReadIndex.NAME},${databaseEntryCount} entries,`
+ + `read ${readCount} entries,${entrySize} B/entry,${batchSize} ops/tx,`
+ + `${this._sync? '' : 'a'}sync`;
+ }
+
+
+ async _init() {
+ await super._init();
+ // fill up the database
+ const objectStore = this._db.getObjectStore(BenchmarkReadIndex.TABLE_NAME);
+ await BenchmarkUtils.fillObjectStoreWithIndex(objectStore, this._databaseEntryCount, this._entrySize, 1000, false,
+ this._entryKeys, this._indexKeys);
+ }
+
+
+ async _benchmark(stats) {
+ const readKeys = [];
+ for (let i=0; i {
+ const key = readKeys[index];
+ const i = transaction.index('index');
+ return i.values(this.jdb.KeyRange.only(key));
+ };
+ const objectStore = this._db.getObjectStore(BenchmarkReadIndex.TABLE_NAME);
+ const result = await BenchmarkUtils.performBatchOperation(objectStore, this._readCount, this._batchSize,
+ this._sync, readOperation);
+ if (!result.results.every(entry => !!entry)) {
+ console.error('Error reading data from database.');
+ }
+ stats.addReads(this._readCount, this._readCount * this._entrySize, result.totalTime);
+ }
+}
+BenchmarkReadIndex.NAME = 'benchmark-read-index';
+BenchmarkReadIndex.TABLE_NAME = 'default';
+BenchmarkReadIndex.VERSION = 1;
+
+if (typeof(module) !== 'undefined') {
+ module.exports = BenchmarkReadIndex;
+}
diff --git a/benchmark/shared/BenchmarkRunner.js b/benchmark/shared/BenchmarkRunner.js
index 8f1db10..c22643e 100644
--- a/benchmark/shared/BenchmarkRunner.js
+++ b/benchmark/shared/BenchmarkRunner.js
@@ -4,10 +4,11 @@ if (typeof(require) !== 'undefined') {
BenchmarkRead = require('./BenchmarkRead.js');
BenchmarkDelete = require('./BenchmarkDelete.js');
BenchmarkReadFromMultiple = require('./BenchmarkReadFromMultiple.js');
+ BenchmarkReadIndex = require('./BenchmarkReadIndex.js');
}
class BenchmarkRunner {
- static async runBenchmarks(benchmarkUi = null) {
+ static async runBenchmarks(benchmarkUi = null, customJDB = null, options = {}) {
if (benchmarkUi) {
for (const benchmarkDescription of BenchmarkRunner.BenchmarkDescriptions) {
const type = benchmarkDescription.benchmark.NAME;
@@ -25,9 +26,10 @@ class BenchmarkRunner {
let result;
try {
const benchmark = new benchmarkDescription.benchmark(params);
+ benchmark.setJDB(customJDB, options);
result = await benchmark.run(); // eslint-disable-line no-await-in-loop
- } catch(e) {
- console.log('\nSkipped invalid configuration', params, 'because of error', e);
+ } catch (e) {
+ // console.log('\nSkipped invalid configuration', params, 'because of error', e);
result = null;
}
if (benchmarkUi) {
@@ -103,7 +105,7 @@ BenchmarkRunner.BenchmarkDescriptions = [
entryCount: [100, 500, 1000, 10000],
entrySize: [100, 1000, 100000],
batchSize: [1, 100, 500],
- sync: [true, false]
+ sync: [true]
},
{
benchmark: BenchmarkOverwrite,
@@ -111,7 +113,7 @@ BenchmarkRunner.BenchmarkDescriptions = [
overwriteCount: [1000, 10000],
entrySize: [10, 100, 1000],
batchSize: [1, 10, 100, 1000],
- sync: [true, false]
+ sync: [true]
},
{
benchmark: BenchmarkRead,
@@ -119,7 +121,7 @@ BenchmarkRunner.BenchmarkDescriptions = [
readCount: [10, 100, 1000],
entrySize: [100, 1000, 1000000],
batchSize: [1, 10, 100],
- sync: [true, false]
+ sync: [true]
},
{
benchmark: BenchmarkDelete,
@@ -127,7 +129,7 @@ BenchmarkRunner.BenchmarkDescriptions = [
deleteCount: [10, 100, 1000],
entrySize: [100, 1000],
batchSize: [1, 10, 100],
- sync: [true, false]
+ sync: [true]
},
{
benchmark: BenchmarkReadFromMultiple,
@@ -136,7 +138,23 @@ BenchmarkRunner.BenchmarkDescriptions = [
totalEntrySize: [100, 1000],
numberTables: [1, 2, 3],
batchSize: [1, 10, 100],
- sync: [true, false]
+ sync: [true]
+ },
+ {
+ benchmark: BenchmarkReadIndex,
+ databaseEntryCount: [100, 500, 1000],
+ readCount: [10, 100, 1000],
+ entrySize: [100, 1000, 1000000],
+ batchSize: [1, 10, 100],
+ sync: [true]
+ },
+ {
+ benchmark: BenchmarkReadIndex,
+ databaseEntryCount: [100000],
+ readCount: [10, 100, 1000],
+ entrySize: [100, 1000],
+ batchSize: [1, 10, 100],
+ sync: [true]
}
];
diff --git a/benchmark/shared/BenchmarkUtils.js b/benchmark/shared/BenchmarkUtils.js
index 70668b2..f67394a 100644
--- a/benchmark/shared/BenchmarkUtils.js
+++ b/benchmark/shared/BenchmarkUtils.js
@@ -32,6 +32,37 @@ class BenchmarkUtils {
}
+ /**
+ * @param {ObjectStore} objectStore
+ * @param {number} entryCount
+ * @param {number} entrySize
+ * @param {number} [batchSize]
+ * @param {boolean} [sync]
+ * @param {Array.} [keys]
+ * @param {Stats} [stats]
+ * @returns {Promise.}
+ */
+ static async fillObjectStoreWithIndex(objectStore, entryCount, entrySize, batchSize=1, sync=false, keys=null, indexKeys=null, stats=null) {
+ const randomData = [];
+ for (let i=0; i {
+ const key = keys ? keys[index] : String(index);
+ const data = randomData[index];
+ await transaction.put(key, data);
+ };
+ const totalTime =
+ (await BenchmarkUtils.performBatchOperation(objectStore, entryCount, batchSize, sync, putEntry)).totalTime;
+ if (stats) {
+ stats.addWrites(entryCount, entryCount*entrySize, totalTime);
+ }
+ }
+
+
/**
* @param {ObjectStore} objectStore
* @param {number} totalCount
@@ -163,7 +194,8 @@ class BenchmarkUtils {
console.log(`%c${str}`, 'color: teal; font-weight: bold;');
} else {
// node
- console.log('\x1b[36m%s\x1b[0m', str);
+ // console.log('\x1b[36m%s\x1b[0m', str);
+ console.log(str);
}
}
}
diff --git a/benchmark/shared/Stats.js b/benchmark/shared/Stats.js
index cebcfa8..c9925f9 100644
--- a/benchmark/shared/Stats.js
+++ b/benchmark/shared/Stats.js
@@ -196,6 +196,10 @@ class Stats {
}
}
+ totalTime() {
+ return `${this.writeTimePerRun + this.readTimePerRun},${Stats._getTimeString(this.writeTimePerRun + this.readTimePerRun)}`;
+ }
+
toString() {
let result = '';
if (this.writes > 0) {
diff --git a/clients/browser/index.html b/clients/browser/index.html
index dfcdbde..6cf65ac 100644
--- a/clients/browser/index.html
+++ b/clients/browser/index.html
@@ -5,7 +5,7 @@
JungleDB
-
+