From 1f07d257068bf3af1bcb0e684eb9174ca8ed09d7 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Tue, 22 Apr 2025 21:24:13 +0200 Subject: [PATCH] test: Benchmark all db types using an encryption mock. --- benchmarks/encryption/log-append.js | 6 +- benchmarks/encryption/log-iterator.js | 65 +++++++++++++++++ benchmarks/encryption/orbitdb-documents.js | 72 +++++++++++++++++++ benchmarks/encryption/orbitdb-events.js | 64 +++++++++++++++++ benchmarks/encryption/orbitdb-keyvalue.js | 64 +++++++++++++++++ benchmarks/encryption/orbitdb-kv-indexed.js | 64 +++++++++++++++++ benchmarks/encryption/orbitdb-replicate.js | 80 +++++++++++++++++++++ 7 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 benchmarks/encryption/log-iterator.js create mode 100644 benchmarks/encryption/orbitdb-documents.js create mode 100644 benchmarks/encryption/orbitdb-events.js create mode 100644 benchmarks/encryption/orbitdb-keyvalue.js create mode 100644 benchmarks/encryption/orbitdb-kv-indexed.js create mode 100644 benchmarks/encryption/orbitdb-replicate.js diff --git a/benchmarks/encryption/log-append.js b/benchmarks/encryption/log-append.js index 91ea4b8..bb35fcd 100644 --- a/benchmarks/encryption/log-append.js +++ b/benchmarks/encryption/log-append.js @@ -1,6 +1,6 @@ -import { Identities, Log } from '../src/index.js' -import { MemoryStorage } from '../src/storage/index.js' -import CustomEncryption from '../test/fixtures/encryption/custom.js' +import { Identities, Log } from '../../src/index.js' +import { MemoryStorage } from '../../src/storage/index.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' // import { MemoryStorage, LevelStorage, LRUStorage } from '../src/storage/index.js' import { rimraf as rmrf } from 'rimraf' diff --git a/benchmarks/encryption/log-iterator.js b/benchmarks/encryption/log-iterator.js new file mode 100644 index 0000000..b75ff2e --- /dev/null +++ b/benchmarks/encryption/log-iterator.js @@ -0,0 +1,65 @@ +import { Identities, Log } from '../../src/index.js' +import { MemoryStorage } from '../../src/storage/index.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' +// import { MemoryStorage, LevelStorage, LRUStorage } from '../src/storage/index.js' +import { rimraf as rmrf } from 'rimraf' + +;(async () => { + console.log('Starting benchmark...') + + await rmrf('./orbitdb') + + const identities = await Identities() + const testIdentity = await identities.createIdentity({ id: 'userA' }) + + // MemoryStorage is the default storage for Log but defining them here + // in case we want to benchmark different storage modules + const entryStorage = await MemoryStorage() + const headsStorage = await MemoryStorage() + const indexStorage = await MemoryStorage() + // Test LRUStorage + // const entryStorage = await LRUStorage() + // const headsStorage = await LRUStorage() + // const indexStorage = await LRUStorage() + // Test LevelStorage + // const entryStorage = await LevelStorage({ path: './logA/entries' }) + // const headsStorage = await LevelStorage({ path: './logA/heads' }) + // const indexStorage = await LevelStorage({ path: './logA/index' }) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const log = await Log(testIdentity, { logId: 'A', entryStorage, headsStorage, indexStorage, encryption: { replicationEncryption, dataEncryption } }) + + const entryCount = 10000 + + console.log(`Append ${entryCount} entries`) + + const startTime1 = new Date().getTime() + for (let i = 0; i < entryCount; i++) { + await log.append(i.toString(), { referencesCount: 0 }) + } + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + + console.log(`Appending ${entryCount} entries took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + console.log(`Iterate ${entryCount} entries`) + const startTime2 = new Date().getTime() + const all = [] + for await (const entry of log.iterator()) { + all.unshift(entry) + } + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Iterating ${all.length} entries took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await rmrf('./orbitdb') + + process.exit(0) +})() diff --git a/benchmarks/encryption/orbitdb-documents.js b/benchmarks/encryption/orbitdb-documents.js new file mode 100644 index 0000000..e9ba312 --- /dev/null +++ b/benchmarks/encryption/orbitdb-documents.js @@ -0,0 +1,72 @@ +import { createOrbitDB } from '../../src/index.js' +// import { createOrbitDB, MemoryStorage } from '../src/index.js' +import { rimraf as rmrf } from 'rimraf' +import createHelia from '../../test/utils/create-helia.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' + +import { EventEmitter } from 'events' +EventEmitter.defaultMaxListeners = 10000 + +;(async () => { + console.log('Starting benchmark...') + + const entryCount = 1000 + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + const ipfs = await createHelia() + const orbitdb = await createOrbitDB({ ipfs }) + + console.log(`Insert ${entryCount} documents`) + + // const entryStorage = await MemoryStorage() + // const headsStorage = await MemoryStorage() + // const indexStorage = await MemoryStorage() + + // const db1 = await orbitdb.open('benchmark-documents', { type: 'documents', referencesCount: 16, entryStorage, headsStorage, indexStorage }) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const db1 = await orbitdb.open('benchmark-documents', { type: 'documents', encryption: { replicationEncryption, dataEncryption } }) + + const startTime1 = new Date().getTime() + + for (let i = 0; i < entryCount; i++) { + const doc = { _id: i.toString(), message: 'hello ' + i } + await db1.put(doc) + } + + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + console.log(`Inserting ${entryCount} documents took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + console.log(`Query ${entryCount} documents`) + const startTime2 = new Date().getTime() + + const all = [] + for await (const { key, value } of db1.iterator()) { + all.unshift({ key, value }) + } + + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Querying ${all.length} documents took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await db1.drop() + await db1.close() + + await orbitdb.stop() + await ipfs.stop() + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + process.exit(0) +})() diff --git a/benchmarks/encryption/orbitdb-events.js b/benchmarks/encryption/orbitdb-events.js new file mode 100644 index 0000000..9eadd6d --- /dev/null +++ b/benchmarks/encryption/orbitdb-events.js @@ -0,0 +1,64 @@ +import { createOrbitDB } from '../../src/index.js' +import { rimraf as rmrf } from 'rimraf' +import createHelia from '../../test/utils/create-helia.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' + +import { EventEmitter } from 'events' +EventEmitter.defaultMaxListeners = 10000 + +;(async () => { + console.log('Starting benchmark...') + + const entryCount = 1000 + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + const ipfs = await createHelia() + const orbitdb = await createOrbitDB({ ipfs }) + + console.log(`Create ${entryCount} events`) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const db1 = await orbitdb.open('benchmark-events', { encryption: { replicationEncryption, dataEncryption } }) + + const startTime1 = new Date().getTime() + + for (let i = 0; i < entryCount; i++) { + await db1.add(i.toString()) + } + + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + console.log(`Creating ${entryCount} events took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + console.log(`Iterate ${entryCount} events`) + const startTime2 = new Date().getTime() + + const all = [] + for await (const { key, value } of db1.iterator()) { + all.unshift({ key, value }) + } + + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Iterating ${all.length} events took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await db1.drop() + await db1.close() + + await orbitdb.stop() + await ipfs.stop() + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + process.exit(0) +})() diff --git a/benchmarks/encryption/orbitdb-keyvalue.js b/benchmarks/encryption/orbitdb-keyvalue.js new file mode 100644 index 0000000..d76049b --- /dev/null +++ b/benchmarks/encryption/orbitdb-keyvalue.js @@ -0,0 +1,64 @@ +import { createOrbitDB } from '../../src/index.js' +import { rimraf as rmrf } from 'rimraf' +import createHelia from '../../test/utils/create-helia.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' + +import { EventEmitter } from 'events' +EventEmitter.defaultMaxListeners = 10000 + +;(async () => { + console.log('Starting benchmark...') + + const entryCount = 1000 + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + const ipfs = await createHelia() + const orbitdb = await createOrbitDB({ ipfs }) + + console.log(`Set ${entryCount} keys/values`) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const db1 = await orbitdb.open('benchmark-keyvalue', { type: 'keyvalue', encryption: { replicationEncryption, dataEncryption } }) + + const startTime1 = new Date().getTime() + + for (let i = 0; i < entryCount; i++) { + await db1.set(i.toString(), 'hello' + i) + } + + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + console.log(`Setting ${entryCount} key/values took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + console.log(`Iterate ${entryCount} key/values`) + const startTime2 = new Date().getTime() + + const all = [] + for await (const { key, value } of db1.iterator()) { + all.unshift({ key, value }) + } + + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Iterating ${all.length} key/values took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await db1.drop() + await db1.close() + + await orbitdb.stop() + await ipfs.stop() + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + process.exit(0) +})() diff --git a/benchmarks/encryption/orbitdb-kv-indexed.js b/benchmarks/encryption/orbitdb-kv-indexed.js new file mode 100644 index 0000000..aad4c98 --- /dev/null +++ b/benchmarks/encryption/orbitdb-kv-indexed.js @@ -0,0 +1,64 @@ +import { createOrbitDB, KeyValueIndexed } from '../../src/index.js' +import { rimraf as rmrf } from 'rimraf' +import createHelia from '../../test/utils/create-helia.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' + +import { EventEmitter } from 'events' +EventEmitter.defaultMaxListeners = 10000 + +;(async () => { + console.log('Starting benchmark...') + + const entryCount = 1000 + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + const ipfs = await createHelia() + const orbitdb = await createOrbitDB({ ipfs }) + + console.log(`Set ${entryCount} keys/values`) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const db1 = await orbitdb.open('benchmark-keyvalue-indexed', { Database: KeyValueIndexed(), encryption: { replicationEncryption, dataEncryption } }) + + const startTime1 = new Date().getTime() + + for (let i = 0; i < entryCount; i++) { + await db1.set(i.toString(), 'hello' + i) + } + + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + console.log(`Setting ${entryCount} key/values took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + console.log(`Iterate ${entryCount} key/values`) + const startTime2 = new Date().getTime() + + const all = [] + for await (const { key, value } of db1.iterator()) { + all.unshift({ key, value }) + } + + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Iterating ${all.length} key/values took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await db1.drop() + await db1.close() + + await orbitdb.stop() + await ipfs.stop() + + await rmrf('./ipfs') + await rmrf('./orbitdb') + + process.exit(0) +})() diff --git a/benchmarks/encryption/orbitdb-replicate.js b/benchmarks/encryption/orbitdb-replicate.js new file mode 100644 index 0000000..363340a --- /dev/null +++ b/benchmarks/encryption/orbitdb-replicate.js @@ -0,0 +1,80 @@ +import { createOrbitDB } from '../../src/index.js' +import { rimraf as rmrf } from 'rimraf' +import createHelia from '../../test/utils/create-helia.js' +import connectPeers from '../../test/utils/connect-nodes.js' +import waitFor from '../../test/utils/wait-for.js' +import CustomEncryption from '../../test/fixtures/encryption/custom.js' + +import { EventEmitter } from 'events' +EventEmitter.defaultMaxListeners = 10000 + +;(async () => { + console.log('Starting benchmark...') + + const entryCount = 1000 + + await rmrf('./orbitdb1') + await rmrf('./orbitdb2') + + const [ipfs1, ipfs2] = await Promise.all([createHelia(), createHelia()]) + + const orbitdb1 = await createOrbitDB({ ipfs: ipfs1, directory: './orbitdb1' }) + const orbitdb2 = await createOrbitDB({ ipfs: ipfs2, directory: './orbitdb2' }) + + await connectPeers(ipfs1, ipfs2) + + console.log(`Add ${entryCount} events`) + + const replicationEncryption = await CustomEncryption() + const dataEncryption = await CustomEncryption() + + const db1 = await orbitdb1.open('benchmark-replication', { type: 'events', encryption: { replicationEncryption, dataEncryption } }) + + const startTime1 = new Date().getTime() + + for (let i = 0; i < entryCount; i++) { + await db1.add('hello' + i) + } + + const endTime1 = new Date().getTime() + const duration1 = endTime1 - startTime1 + const operationsPerSecond1 = Math.floor(entryCount / (duration1 / 1000)) + const millisecondsPerOp1 = duration1 / entryCount + console.log(`Adding ${entryCount} events took ${duration1} ms, ${operationsPerSecond1} ops/s, ${millisecondsPerOp1} ms/op`) + + const db2 = await orbitdb2.open(db1.address, { encryption: { replicationEncryption, dataEncryption } }) + + const startTime2 = new Date().getTime() + + let connected = false + + const onJoin = async (peerId) => (connected = true) + const onError = async (err) => console.error(err) + + db2.events.on('join', onJoin) + db2.events.on('error', onError) + + await waitFor(() => connected, () => true) + + const endTime2 = new Date().getTime() + const duration2 = endTime2 - startTime2 + const operationsPerSecond2 = Math.floor(entryCount / (duration2 / 1000)) + const millisecondsPerOp2 = duration2 / entryCount + + console.log(`Replicating ${entryCount} events took ${duration2} ms, ${operationsPerSecond2} ops/s, ${millisecondsPerOp2} ms/op`) + + await db1.drop() + await db1.close() + await db2.drop() + await db2.close() + + await orbitdb1.stop() + await orbitdb2.stop() + await ipfs1.stop() + await ipfs2.stop() + + await rmrf('./orbitdb1') + await rmrf('./orbitdb2') + + process.exit(0) +})()