From abc0b425cbce578e940f1d26f75680befdab728e Mon Sep 17 00:00:00 2001 From: DanCodes Date: Sun, 7 Apr 2024 21:07:29 +0100 Subject: [PATCH] feat: overwrite, benchmark, setMany, index --- benchmark/.gitignore | 2 +- benchmark/README.md | 65 ++++ benchmark/docker-compose.yml | 25 ++ benchmark/package.json | 7 +- benchmark/src/index.ts | 222 ++++++----- crates/lib/src/lib.rs | 102 +++++- crates/lib/src/utils.rs | 14 + crates/migration/src/lib.rs | 13 +- .../src/m20220101_000001_create_table.rs | 9 +- .../src/m20240407_192852_add_indexes.rs | 27 ++ src/index.ts | 17 + src/native.d.ts | 4 + tests/index.test.ts | 24 ++ yarn.lock | 345 +----------------- 14 files changed, 394 insertions(+), 482 deletions(-) create mode 100644 benchmark/README.md create mode 100644 benchmark/docker-compose.yml create mode 100644 crates/migration/src/m20240407_192852_add_indexes.rs diff --git a/benchmark/.gitignore b/benchmark/.gitignore index 1269488..885029a 100644 --- a/benchmark/.gitignore +++ b/benchmark/.gitignore @@ -1 +1 @@ -data +*.sqlite* \ No newline at end of file diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000..84d48d6 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,65 @@ +# BrineDB Benchmark + +To run the benchmark, you need to follow these steps: + +1. Run ``docker compose up -d`` +2. Run ``cd .. && yarn release-native && cd benchmark`` +3. Run ``yarn bench`` + +The benchmark will run and output the results to the console. + +## Benchmark Results + +Valid as of 2024-04-07 + +```bash +😃 Results for: SQLite (Memory) +┌─────────┬───────────┬──────────┬───────────────────┬──────────┬─────────┬───────────────────┐ +│ (index) │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │ Average Time (ms) │ +├─────────┼───────────┼──────────┼───────────────────┼──────────┼─────────┼───────────────────┤ +│ 0 │ 'get' │ '19,244' │ 51962.33089113228 │ '±1.74%' │ 19245 │ '0.052' │ +│ 1 │ 'set' │ '18,509' │ 54027.41947847479 │ '±2.45%' │ 18523 │ '0.054' │ +│ 2 │ 'count' │ '4,056' │ 246511.4823761241 │ '±0.25%' │ 4057 │ '0.247' │ +│ 3 │ 'setMany' │ '1,186' │ 842960.5206401688 │ '±4.24%' │ 1187 │ '0.843' │ +└─────────┴───────────┴──────────┴───────────────────┴──────────┴─────────┴───────────────────┘ + +😃 Results for: SQLite (File) +┌─────────┬───────────┬──────────┬────────────────────┬──────────┬─────────┬───────────────────┐ +│ (index) │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │ Average Time (ms) │ +├─────────┼───────────┼──────────┼────────────────────┼──────────┼─────────┼───────────────────┤ +│ 0 │ 'get' │ '17,053' │ 58637.99859266467 │ '±1.57%' │ 17054 │ '0.059' │ +│ 1 │ 'set' │ '98' │ 10146073.959595695 │ '±6.38%' │ 99 │ '10.146' │ +│ 2 │ 'count' │ '189' │ 5266332.842932184 │ '±1.59%' │ 191 │ '5.266' │ +│ 3 │ 'setMany' │ '1,475' │ 677721.3696680956 │ '±4.24%' │ 1477 │ '0.678' │ +└─────────┴───────────┴──────────┴────────────────────┴──────────┴─────────┴───────────────────┘ + +😃 Results for: PostgreSQL +┌─────────┬───────────┬─────────┬────────────────────┬──────────┬─────────┬───────────────────┐ +│ (index) │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │ Average Time (ms) │ +├─────────┼───────────┼─────────┼────────────────────┼──────────┼─────────┼───────────────────┤ +│ 0 │ 'get' │ '4,884' │ 204745.00000005757 │ '±1.48%' │ 4885 │ '0.205' │ +│ 1 │ 'set' │ '1,730' │ 577933.152512942 │ '±1.78%' │ 1731 │ '0.578' │ +│ 2 │ 'count' │ '12' │ 80366305.00000095 │ '±1.26%' │ 13 │ '80.366' │ +│ 3 │ 'setMany' │ '445' │ 2243906.7219727584 │ '±2.40%' │ 446 │ '2.244' │ +└─────────┴───────────┴─────────┴────────────────────┴──────────┴─────────┴───────────────────┘ + +😃 Results for: MySQL +┌─────────┬───────────┬─────────┬────────────────────┬───────────┬─────────┬───────────────────┐ +│ (index) │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │ Average Time (ms) │ +├─────────┼───────────┼─────────┼────────────────────┼───────────┼─────────┼───────────────────┤ +│ 0 │ 'get' │ '3,631' │ 275340.9485132162 │ '±1.28%' │ 3632 │ '0.275' │ +│ 1 │ 'set' │ '399' │ 2502239.482499499 │ '±12.75%' │ 400 │ '2.502' │ +│ 2 │ 'count' │ '11' │ 84151469.41666414 │ '±19.07%' │ 12 │ '84.151' │ +│ 3 │ 'setMany' │ '747' │ 1337851.9331546512 │ '±2.58%' │ 748 │ '1.338' │ +└─────────┴───────────┴─────────┴────────────────────┴───────────┴─────────┴───────────────────┘ + +😃 Results for: MariaDB +┌─────────┬───────────┬─────────┬────────────────────┬──────────┬─────────┬───────────────────┐ +│ (index) │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │ Average Time (ms) │ +├─────────┼───────────┼─────────┼────────────────────┼──────────┼─────────┼───────────────────┤ +│ 0 │ 'get' │ '3,572' │ 279935.25776648754 │ '±2.08%' │ 3573 │ '0.280' │ +│ 1 │ 'set' │ '1,215' │ 822408.2055921347 │ '±6.10%' │ 1216 │ '0.822' │ +│ 2 │ 'count' │ '1' │ 977628002.3000028 │ '±2.41%' │ 10 │ '977.628' │ +│ 3 │ 'setMany' │ '630' │ 1584830.0000005558 │ '±2.99%' │ 631 │ '1.585' │ +└─────────┴───────────┴─────────┴────────────────────┴──────────┴─────────┴───────────────────┘ +``` \ No newline at end of file diff --git a/benchmark/docker-compose.yml b/benchmark/docker-compose.yml new file mode 100644 index 0000000..40f7df7 --- /dev/null +++ b/benchmark/docker-compose.yml @@ -0,0 +1,25 @@ +services: + mysql: + image: mysql + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: brinedb + ports: + - "3306:3306" + + postgres: + image: postgres + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: root + POSTGRES_DB: brinedb + ports: + - "5432:5432" + + mariadb: + image: mariadb + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: brinedb + ports: + - "3307:3306" \ No newline at end of file diff --git a/benchmark/package.json b/benchmark/package.json index 05dfbda..b4a5138 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -2,13 +2,12 @@ "name": "brine-benchmark", "scripts": { "build": "tsup", - "start": "rm data/*; node dist/index.js" + "start": "node dist/index.js", + "bench": "yarn build && yarn start" }, "dependencies": { "@favware/colorette-spinner": "^1.0.1", - "@joshdb/core": "npm:^1.2.7", - "@joshdb/sqlite": "npm:^1.1.9", - "better-sqlite3": "latest" + "tinybench": "^2.6.0" }, "devDependencies": { "tsup": "^8.0.2" diff --git a/benchmark/src/index.ts b/benchmark/src/index.ts index 4d93c34..545e3bc 100644 --- a/benchmark/src/index.ts +++ b/benchmark/src/index.ts @@ -1,150 +1,132 @@ -import { Brine } from "../../dist"; -import Josh from "@joshdb/core"; -// @ts-expect-error 7016 -import JoshSqlite from "@joshdb/sqlite"; +import { Brine } from "../../"; import { Spinner } from "@favware/colorette-spinner"; import { BrineDatabases } from "../../src"; +import { Bench } from "tinybench"; -const runs = 100; -const databaseSize = 5; +const randomData = (length: number) => { + const chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; -console.log( - `\nBrine Benchmark commencing, runs set at ${runs} and ${databaseSize} database size.\n`, -); - -interface kv { - set: (key: string, value: string) => Promise; - get: (key: string) => Promise; - clear: () => Promise; -} - -const test = async (store: kv) => { - const start = performance.now(); + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } - const randomKey = Math.random().toString(36).substring(7); - const randomValue = Math.random().toString(36).substring(7); + return result; +}; - await store.set(randomKey, randomValue); - console.log(await store.get(randomKey)); +const benchme = async (name: string, db: Brine) => { + const spinner = new Spinner("Initializing database"); + const bench = new Bench({ time: 1000, warmupTime: 500 }); - const end = performance.now(); + spinner.start(); - return end - start; -}; + await db.init(); -const spinner = new Spinner("Benchmark"); -const benchmark = async (name: string, runner: kv) => { - spinner.start({ - text: `Benchmarking (${name}): 0/${runs}`, + spinner.update({ + text: "Setting up database", }); - let total = 0; - let lastUpdate = Date.now(); + await db.clear(); - await runner.clear(); + const setInitialManyData: [string, string][] = []; + + for (let i = 0; i < 1_000_000; i++) { + setInitialManyData.push([`key-${i}`, randomData(100)]); - for (let i = 0; i < runs; i++) { - total += await test(runner); spinner.update({ - text: `Benchmarking (${name}): ${i + 1}/${runs}`, + text: `Setting up database (${i + 1}/1000000) (${( + (i / 1_000_000) * + 100 + ).toFixed(2)}%)`, }); - - if (lastUpdate + 50 < Date.now()) { - lastUpdate = Date.now(); - spinner.spin(); - } } - return { - [name]: { - "Average (ms)": (total / runs).toFixed(3), - "Operations (op/s)": Math.round(runs / (total / 1000)).toLocaleString(), - "Total (s)": (total / 1000).toFixed(2), - }, - }; -}; - -(async () => { - const josh = new Josh({ - name: "josh", - provider: JoshSqlite, + spinner.update({ + text: "Setting up database", }); - const joshResults = await benchmark("Josh (SQLite)", { - set: async (key, value) => { - await josh.set(key, value); - }, - get: async (key) => { - await josh.get(key); - }, - clear: async () => { - await josh.delete(josh.all); - }, - }); + await db.setMany(setInitialManyData); - const brine_postgres = new Brine( - BrineDatabases.postgres.build({ - host: "localhost", - port: 5432, - user: "root", - password: "root", - database: "brine", - }), + const setManyData: [string, string][] = Array.from( + { length: 100 }, + (_, i) => [`key-many-${i}`, randomData(100)], ); - await brine_postgres.init(); - - const brineResults = await benchmark("Brine (Postgres)", { - set: async (key, value) => { - await brine_postgres.set(key, value); - }, - get: async (key) => { - await brine_postgres.get(key); - }, - clear: async () => { - await brine_postgres.clear(); - }, + bench + .add("get", async () => { + await db.get(`key-${Math.floor(Math.random() * 1000)}`); + }) + .add("set", async () => { + await db.set(`key-${Math.floor(Math.random() * 1000)}`, randomData(100)); + }) + .add("count", async () => { + await db.count(); + }) + .add("setMany", async () => { + await db.setMany(setManyData); + }); + + spinner.update({ + text: "Running warmup", }); - const brine_sqlite = new Brine( - BrineDatabases.sqlite.file("./data/brine.sqlite"), - ); + await bench.warmup(); - await brine_sqlite.init(); - - const brineResultsSqlite = await benchmark("Brine (SQLite)", { - set: async (key, value) => { - await brine_sqlite.set(key, value); - }, - get: async (key) => { - await brine_sqlite.get(key); - }, - clear: async () => { - await brine_sqlite.clear(); - }, + spinner.update({ + text: "Running benchmarks", }); - const brine_memory = new Brine(BrineDatabases.sqlite.memory); + await bench.run(); + await db.close(); - await brine_memory.init(); + spinner.stop(); - const brineResultsMemory = await benchmark("Brine (Memory)", { - set: async (key, value) => { - await brine_memory.set(key, value); - }, - get: async (key) => { - await brine_memory.get(key); - }, - clear: async () => { - await brine_memory.clear(); - }, - }); + // clear line + process.stdout.moveCursor(0, -1); + process.stdout.clearLine(1); - spinner.success({ text: "Benchmarking complete!" }); - console.table({ - ...joshResults, - ...brineResults, - ...brineResultsSqlite, - ...brineResultsMemory, - }); -})(); + const table = bench.table(); + const finalTable: Record[] = []; + + console.log(`😃 Results for: ${name}\n`); // Add Average Time (ms) column based on "Average Time (ns)" column + + for (const row of table) { + if (!row) continue; + if (typeof row["Average Time (ns)"] !== "number") continue; + + finalTable.push({ + ...row, + "Average Time (ms)": (row["Average Time (ns)"] / 1000000).toFixed(3), + }); + } + + console.table(finalTable); +}; + +(async () => { + const login = { + user: "root", + password: "root", + database: "brinedb", + }; + + const sqlite_memory = new Brine(BrineDatabases.sqlite.memory); + const sqlite_file = new Brine(BrineDatabases.sqlite.file("benchmark.sqlite")); + const postgres = new Brine(BrineDatabases.postgres.build(login)); + const mysql = new Brine(BrineDatabases.mysql.build(login)); + const mariadb = new Brine( + BrineDatabases.mysql.build({ + ...login, + port: 3307, + }), + ); + + await benchme("SQLite (Memory)", sqlite_memory); + await benchme("SQLite (File)", sqlite_file); + await benchme("PostgreSQL", postgres); + await benchme("MySQL", mysql); + await benchme("MariaDB", mariadb); + + console.log("✅ All benchmarks complete"); +})().catch(console.error); diff --git a/crates/lib/src/lib.rs b/crates/lib/src/lib.rs index 17224cb..d486f22 100644 --- a/crates/lib/src/lib.rs +++ b/crates/lib/src/lib.rs @@ -3,6 +3,7 @@ use brinedb_entity::doc::Column as DocumentColumn; use brinedb_entity::doc::Entity as Document; use migration::Migrator; use migration::MigratorTrait; +use migration::OnConflict; use neon::prelude::*; use sea_orm::prelude::*; use sea_orm::Set; @@ -58,12 +59,12 @@ fn get(mut cx: FunctionContext) -> JsResult { rt.spawn(async move { let connection = connection(connection_uri).await.expect("Unable to connect"); - let model = Document::find_by_id(&key) + let res = Document::find_by_id(&key) .one(connection) .await .expect("Unable to find key"); - deferred.settle_with(&channel, move |mut cx| match model { + deferred.settle_with(&channel, move |mut cx| match res { Some(doc) => Ok(cx.string(doc.value)), None => cx.throw_error("Key not found"), }); @@ -85,15 +86,89 @@ fn set(mut cx: FunctionContext) -> JsResult { rt.spawn(async move { let connection = connection(connection_uri).await.expect("Unable to connect"); + // if it already exists, update it let model = ActiveDocumentModel { key: Set(key.clone()), value: Set(value.clone()), }; - Document::insert(model) + let res = Document::insert(model) + .on_conflict( + OnConflict::column(DocumentColumn::Key) + .update_column(DocumentColumn::Value) + .to_owned(), + ) .exec(connection) .await - .expect("Unable to insert key"); + .map_err(|err| err.to_string()); + + deferred.settle_with(&channel, move |mut cx| match res { + Ok(_) => Ok(cx.undefined()), + Err(err) => cx.throw_error(err), + }); + }); + + Ok(promise) +} + +fn set_many(mut cx: FunctionContext) -> JsResult { + let connection_uri = cx.argument::(0)?.value(&mut cx); + let pairs = cx.argument::(1)?; + + let rt = runtime(&mut cx)?; + let channel = cx.channel(); + + let (deferred, promise) = cx.promise(); + + let mut pairs_vec = vec![]; + + for i in 0..pairs.len(&mut cx) { + let pair = pairs + .get::(&mut cx, i) + .expect("Invalid array entry"); + + let key = pair + .get::(&mut cx, 0) + .expect("Invalid array entry") + .value(&mut cx); + + let value = pair + .get::(&mut cx, 1) + .expect("Invalid array entry") + .value(&mut cx); + + pairs_vec.push((key, value)); + } + + rt.spawn(async move { + let connection = connection(connection_uri).await.expect("Unable to connect"); + + let models = pairs_vec + .iter() + .map(|(key, value)| ActiveDocumentModel { + key: Set(key.clone()), + value: Set(value.clone()), + }) + .collect::>(); + + for chunk in models.chunks(1000) { + let res = Document::insert_many(chunk.to_vec()) + .on_conflict( + OnConflict::column(DocumentColumn::Key) + .update_column(DocumentColumn::Value) + .to_owned(), + ) + .exec(connection) + .await + .map_err(|err| err.to_string()); + + if let Err(err) = res { + deferred.settle_with(&channel, move |mut cx| { + cx.throw_error::>(err) + }); + return; + } + } deferred.settle_with(&channel, move |mut cx| Ok(cx.undefined())); }); @@ -112,12 +187,15 @@ fn clear(mut cx: FunctionContext) -> JsResult { rt.spawn(async move { let connection = connection(connection_uri).await.expect("Unable to connect"); - Document::delete_many() + let res = Document::delete_many() .exec(connection) .await - .expect("Unable to clear all keys"); + .map_err(|err| err.to_string()); - deferred.settle_with(&channel, move |mut cx| Ok(cx.undefined())); + deferred.settle_with(&channel, move |mut cx| match res { + Ok(_) => Ok(cx.undefined()), + Err(err) => cx.throw_error(err), + }); }); Ok(promise) @@ -220,13 +298,16 @@ fn has(mut cx: FunctionContext) -> JsResult { rt.spawn(async move { let connection = connection(connection_uri).await.expect("Unable to connect"); - let has = Document::find() + let res = Document::find() .filter(DocumentColumn::Key.eq(key)) .count(connection) .await - .expect("Unable to count keys"); + .map_err(|err| err.to_string()); - deferred.settle_with(&channel, move |mut cx| Ok(cx.boolean(has > 0))); + deferred.settle_with(&channel, move |mut cx| match res { + Ok(count) => Ok(cx.boolean(count > 0)), + Err(err) => cx.throw_error(err), + }); }); Ok(promise) @@ -264,5 +345,6 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> { cx.export_function("count", count)?; cx.export_function("has", has)?; cx.export_function("close", close)?; + cx.export_function("setMany", set_many)?; Ok(()) } diff --git a/crates/lib/src/utils.rs b/crates/lib/src/utils.rs index 2176e4a..29ab389 100644 --- a/crates/lib/src/utils.rs +++ b/crates/lib/src/utils.rs @@ -11,11 +11,25 @@ pub fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> { } pub static mut DATABASE: AsyncOnceCell = AsyncOnceCell::new(); +pub static mut DATABASE_URI: OnceCell = OnceCell::new(); pub async fn connection<'a>( connection_uri: String, ) -> Result<&'static DatabaseConnection, sea_orm::DbErr> { unsafe { + let stored_uri = DATABASE_URI.get_or_init(|| connection_uri.clone()); + + if stored_uri != &connection_uri { + let old_connection = DATABASE.take(); + + if let Some(old_connection) = old_connection { + old_connection.close().await?; + } + + DATABASE_URI.take(); + DATABASE_URI.set(connection_uri.clone()).unwrap(); + } + DATABASE .get_or_try_init(async { Database::connect(connection_uri).await }) .await diff --git a/crates/migration/src/lib.rs b/crates/migration/src/lib.rs index 2c605af..80f1177 100644 --- a/crates/migration/src/lib.rs +++ b/crates/migration/src/lib.rs @@ -1,12 +1,23 @@ pub use sea_orm_migration::prelude::*; mod m20220101_000001_create_table; +mod m20240407_192852_add_indexes; pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![Box::new(m20220101_000001_create_table::Migration)] + vec![ + Box::new(m20220101_000001_create_table::Migration), + Box::new(m20240407_192852_add_indexes::Migration), + ] } } + +#[derive(DeriveIden)] +pub enum Brine { + Table, + Key, + Value, +} diff --git a/crates/migration/src/m20220101_000001_create_table.rs b/crates/migration/src/m20220101_000001_create_table.rs index a2caa8a..83a8a9c 100644 --- a/crates/migration/src/m20220101_000001_create_table.rs +++ b/crates/migration/src/m20220101_000001_create_table.rs @@ -1,5 +1,7 @@ use sea_orm_migration::prelude::*; +use crate::Brine; + #[derive(DeriveMigrationName)] pub struct Migration; @@ -22,10 +24,3 @@ impl MigrationTrait for Migration { Ok(()) } } - -#[derive(DeriveIden)] -enum Brine { - Table, - Key, - Value, -} diff --git a/crates/migration/src/m20240407_192852_add_indexes.rs b/crates/migration/src/m20240407_192852_add_indexes.rs new file mode 100644 index 0000000..39ffa1c --- /dev/null +++ b/crates/migration/src/m20240407_192852_add_indexes.rs @@ -0,0 +1,27 @@ +use sea_orm_migration::prelude::*; + +use crate::Brine; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_index( + Index::create() + .table(Brine::Table) + .col(Brine::Key) + .name("idx_key") + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_index(Index::drop().table(Brine::Table).name("idx_key").to_owned()) + .await + } +} diff --git a/src/index.ts b/src/index.ts index dbe647e..4f01062 100644 --- a/src/index.ts +++ b/src/index.ts @@ -227,6 +227,23 @@ class Brine { return value; } + /** + * Set many keys in the database + * + * @param data An array of 2d arrays containing keys and values + * @returns Promise + */ + public async setMany(data: [string, T][]) { + const serializedData = await Promise.all( + data.map(async ([key, value]) => [key, await this.serialize(value)]), + ); + + await this.internals.setMany( + this.connectionURI, + serializedData as [string, string][], + ); + } + /** * Close the connection to the database * diff --git a/src/native.d.ts b/src/native.d.ts index d01d4db..a501b32 100644 --- a/src/native.d.ts +++ b/src/native.d.ts @@ -18,4 +18,8 @@ declare module "*.node" { export function count(connectionURI: string): Promise; export function has(connectionURI: string, key: string): Promise; export function close(): Promise; + export function setMany( + connectionURI: string, + data: [string, string][], + ): Promise; } diff --git a/tests/index.test.ts b/tests/index.test.ts index a4675ab..689b6cb 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -34,6 +34,12 @@ describe("Test suite", () => { }); }); + test("can set overwrite a value", async () => { + const value = await brine.set("hello", "world"); + + expect(value).toBe("world"); + }); + test("can get a value", async () => { const value = await brine.get("hello"); @@ -111,6 +117,24 @@ describe("Test suite", () => { expect(value).toBe(null); }); + test("can set many", async () => { + const data: [string, string][] = [ + ["key1", "value1"], + ["key2", "value2"], + ["key3", "value3"], + ]; + + await brine.setMany(data); + + const value1 = await brine.get("key1"); + const value2 = await brine.get("key2"); + const value3 = await brine.get("key3"); + + expect(value1).toBe("value1"); + expect(value2).toBe("value2"); + expect(value3).toBe("value3"); + }); + test("can close", async () => { await brine.close(); diff --git a/yarn.lock b/yarn.lock index 1b54a45..d254369 100644 --- a/yarn.lock +++ b/yarn.lock @@ -704,28 +704,6 @@ __metadata: languageName: node linkType: hard -"@joshdb/core@npm:^1.2.7": - version: 1.2.7 - resolution: "@joshdb/core@npm:1.2.7" - dependencies: - lodash: ^4.17.20 - serialize-javascript: ^6.0.0 - checksum: 85facd2ece1b90a2f6e23458b738e69256a3c1a957ff7a9aff6faa69c75dac99541d352df12761ee35b7446c5f3ee43cce92b6c569958afb2f54da7ad1ba8057 - languageName: node - linkType: hard - -"@joshdb/sqlite@npm:^1.1.9": - version: 1.1.9 - resolution: "@joshdb/sqlite@npm:1.1.9" - dependencies: - better-sqlite3: latest - lodash: ^4.17.15 - on-change: ^2.1.2 - serialize-javascript: ^5.0.1 - checksum: 676b899760bc7a7baeda0cc64c13ab7394ea15b76a7929b19e89ad3687d6f8e78a14325f8470cd78200f130fdba6b7fa9cd7501a6e4d7bda794a3a627d605d0e - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -1566,24 +1544,6 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 - languageName: node - linkType: hard - -"better-sqlite3@npm:latest": - version: 9.4.5 - resolution: "better-sqlite3@npm:9.4.5" - dependencies: - bindings: ^1.5.0 - node-gyp: latest - prebuild-install: ^7.1.1 - checksum: ca3b533ac9cbc273308f3bbfe617198c5a572344b4a33f1ccd7af6233634b3d263c776bbc58ddc43e8dad440c61d6f1b669046036811942405c680ecf17b037e - languageName: node - linkType: hard - "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -1591,26 +1551,6 @@ __metadata: languageName: node linkType: hard -"bindings@npm:^1.5.0": - version: 1.5.0 - resolution: "bindings@npm:1.5.0" - dependencies: - file-uri-to-path: 1.0.0 - checksum: 65b6b48095717c2e6105a021a7da4ea435aa8d3d3cd085cb9e85bcb6e5773cf318c4745c3f7c504412855940b585bdf9b918236612a1c7a7942491de176f1ae7 - languageName: node - linkType: hard - -"bl@npm:^4.0.3": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: ^5.5.0 - inherits: ^2.0.4 - readable-stream: ^3.4.0 - checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -1644,9 +1584,7 @@ __metadata: resolution: "brine-benchmark@workspace:benchmark" dependencies: "@favware/colorette-spinner": ^1.0.1 - "@joshdb/core": "npm:^1.2.7" - "@joshdb/sqlite": "npm:^1.1.9" - better-sqlite3: latest + tinybench: ^2.6.0 tsup: ^8.0.2 languageName: unknown linkType: soft @@ -1687,16 +1625,6 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.5.0": - version: 5.7.1 - resolution: "buffer@npm:5.7.1" - dependencies: - base64-js: ^1.3.1 - ieee754: ^1.1.13 - checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 - languageName: node - linkType: hard - "bundle-require@npm:^4.0.0": version: 4.0.1 resolution: "bundle-require@npm:4.0.1" @@ -1811,13 +1739,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^1.1.1": - version: 1.1.4 - resolution: "chownr@npm:1.1.4" - checksum: 115648f8eb38bac5e41c3857f3e663f9c39ed6480d1349977c4d96c95a47266fcacc5a5aabf3cb6c481e22d72f41992827db47301851766c4fd77ac21a4f081d - languageName: node - linkType: hard - "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -1915,15 +1836,6 @@ __metadata: languageName: node linkType: hard -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: ^3.1.0 - checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 - languageName: node - linkType: hard - "deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" @@ -1933,13 +1845,6 @@ __metadata: languageName: node linkType: hard -"deep-extend@npm:^0.6.0": - version: 0.6.0 - resolution: "deep-extend@npm:0.6.0" - checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 - languageName: node - linkType: hard - "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -2000,15 +1905,6 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" - dependencies: - once: ^1.4.0 - checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b - languageName: node - linkType: hard - "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -2251,13 +2147,6 @@ __metadata: languageName: node linkType: hard -"expand-template@npm:^2.0.3": - version: 2.0.3 - resolution: "expand-template@npm:2.0.3" - checksum: 588c19847216421ed92befb521767b7018dc88f88b0576df98cb242f20961425e96a92cbece525ef28cc5becceae5d544ae0f5b9b5e2aa05acb13716ca5b3099 - languageName: node - linkType: hard - "fast-glob@npm:^3.2.9": version: 3.2.12 resolution: "fast-glob@npm:3.2.12" @@ -2280,13 +2169,6 @@ __metadata: languageName: node linkType: hard -"file-uri-to-path@npm:1.0.0": - version: 1.0.0 - resolution: "file-uri-to-path@npm:1.0.0" - checksum: b648580bdd893a008c92c7ecc96c3ee57a5e7b6c4c18a9a09b44fb5d36d79146f8e442578bc0e173dc027adf3987e254ba1dfd6e3ec998b7c282873010502144 - languageName: node - linkType: hard - "fill-range@npm:^7.0.1": version: 7.0.1 resolution: "fill-range@npm:7.0.1" @@ -2296,13 +2178,6 @@ __metadata: languageName: node linkType: hard -"fs-constants@npm:^1.0.0": - version: 1.0.0 - resolution: "fs-constants@npm:1.0.0" - checksum: 18f5b718371816155849475ac36c7d0b24d39a11d91348cfcb308b4494824413e03572c403c86d3a260e049465518c4f0d5bd00f0371cdfcad6d4f30a85b350d - languageName: node - linkType: hard - "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -2418,13 +2293,6 @@ __metadata: languageName: node linkType: hard -"github-from-package@npm:0.0.0": - version: 0.0.0 - resolution: "github-from-package@npm:0.0.0" - checksum: 14e448192a35c1e42efee94c9d01a10f42fe790375891a24b25261246ce9336ab9df5d274585aedd4568f7922246c2a78b8a8cd2571bfe99c693a9718e7dd0e3 - languageName: node - linkType: hard - "glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -2616,13 +2484,6 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.1.13": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e - languageName: node - linkType: hard - "ignore@npm:^5.2.0": version: 5.2.1 resolution: "ignore@npm:5.2.1" @@ -2668,20 +2529,13 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4": +"inherits@npm:2, inherits@npm:^2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 languageName: node linkType: hard -"ini@npm:~1.3.0": - version: 1.3.8 - resolution: "ini@npm:1.3.8" - checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 - languageName: node - linkType: hard - "ip@npm:^2.0.0": version: 2.0.0 resolution: "ip@npm:2.0.0" @@ -2892,13 +2746,6 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.15, lodash@npm:^4.17.20": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - "loupe@npm:^2.3.6, loupe@npm:^2.3.7": version: 2.3.7 resolution: "loupe@npm:2.3.7" @@ -3049,13 +2896,6 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 - languageName: node - linkType: hard - "minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -3092,7 +2932,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5": +"minimist@npm:^1.2.5": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -3169,13 +3009,6 @@ __metadata: languageName: node linkType: hard -"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": - version: 0.5.3 - resolution: "mkdirp-classic@npm:0.5.3" - checksum: 3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac - languageName: node - linkType: hard - "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -3231,13 +3064,6 @@ __metadata: languageName: node linkType: hard -"napi-build-utils@npm:^1.0.1": - version: 1.0.2 - resolution: "napi-build-utils@npm:1.0.2" - checksum: 06c14271ee966e108d55ae109f340976a9556c8603e888037145d6522726aebe89dd0c861b4b83947feaf6d39e79e08817559e8693deedc2c94e82c5cbd090c7 - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -3259,15 +3085,6 @@ __metadata: languageName: node linkType: hard -"node-abi@npm:^3.3.0": - version: 3.57.0 - resolution: "node-abi@npm:3.57.0" - dependencies: - semver: ^7.3.5 - checksum: 4ec876ca87ea5c02bdc088cae32fb275368d85113a51a677390bd5e6f9f4fbd85d1a47b00764c05b4a3a16ae83ea42b2b32788bbf6c7d98dfa9f41921e5a2569 - languageName: node - linkType: hard - "node-fetch@npm:^2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -3387,14 +3204,7 @@ __metadata: languageName: node linkType: hard -"on-change@npm:^2.1.2": - version: 2.2.3 - resolution: "on-change@npm:2.2.3" - checksum: 87700c6ba041a438ef32501493a74d9ece7a5c43dcb2464a0ec725319b6318586a56f599b00460eb33c9bd6edda129663ba0af66669b9feb6af33fc83e82bece - languageName: node - linkType: hard - -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -3542,28 +3352,6 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.1.1": - version: 7.1.2 - resolution: "prebuild-install@npm:7.1.2" - dependencies: - detect-libc: ^2.0.0 - expand-template: ^2.0.3 - github-from-package: 0.0.0 - minimist: ^1.2.3 - mkdirp-classic: ^0.5.3 - napi-build-utils: ^1.0.1 - node-abi: ^3.3.0 - pump: ^3.0.0 - rc: ^1.2.7 - simple-get: ^4.0.0 - tar-fs: ^2.0.0 - tunnel-agent: ^0.6.0 - bin: - prebuild-install: bin.js - checksum: 543dadf8c60e004ae9529e6013ca0cbeac8ef38b5f5ba5518cb0b622fe7f8758b34e4b5cb1a791db3cdc9d2281766302df6088bd1a225f206925d6fee17d6c5c - languageName: node - linkType: hard - "pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -3592,16 +3380,6 @@ __metadata: languageName: node linkType: hard -"pump@npm:^3.0.0": - version: 3.0.0 - resolution: "pump@npm:3.0.0" - dependencies: - end-of-stream: ^1.1.0 - once: ^1.3.1 - checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 - languageName: node - linkType: hard - "punycode@npm:^2.1.0": version: 2.1.1 resolution: "punycode@npm:2.1.1" @@ -3616,29 +3394,6 @@ __metadata: languageName: node linkType: hard -"randombytes@npm:^2.1.0": - version: 2.1.0 - resolution: "randombytes@npm:2.1.0" - dependencies: - safe-buffer: ^5.1.0 - checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 - languageName: node - linkType: hard - -"rc@npm:^1.2.7": - version: 1.2.8 - resolution: "rc@npm:1.2.8" - dependencies: - deep-extend: ^0.6.0 - ini: ~1.3.0 - minimist: ^1.2.0 - strip-json-comments: ~2.0.1 - bin: - rc: ./cli.js - checksum: 2e26e052f8be2abd64e6d1dabfbd7be03f80ec18ccbc49562d31f617d0015fbdbcf0f9eed30346ea6ab789e0fdfe4337f033f8016efdbee0df5354751842080e - languageName: node - linkType: hard - "react-is@npm:^18.0.0": version: 18.2.0 resolution: "react-is@npm:18.2.0" @@ -3646,17 +3401,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: ^2.0.3 - string_decoder: ^1.1.1 - util-deprecate: ^1.0.1 - checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d - languageName: node - linkType: hard - "readable-stream@npm:^3.6.0": version: 3.6.0 resolution: "readable-stream@npm:3.6.0" @@ -3828,7 +3572,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -3893,24 +3637,6 @@ __metadata: languageName: node linkType: hard -"serialize-javascript@npm:^5.0.1": - version: 5.0.1 - resolution: "serialize-javascript@npm:5.0.1" - dependencies: - randombytes: ^2.1.0 - checksum: bb45a427690c3d2711e28499de0fbf25036af1e23c63c6a9237ed0aa572fd0941fcdefe50a2dccf26d9df8c8b86ae38659e19d8ba7afd3fbc1f1c7539a2a48d2 - languageName: node - linkType: hard - -"serialize-javascript@npm:^6.0.0": - version: 6.0.2 - resolution: "serialize-javascript@npm:6.0.2" - dependencies: - randombytes: ^2.1.0 - checksum: c4839c6206c1d143c0f80763997a361310305751171dd95e4b57efee69b8f6edd8960a0b7fbfc45042aadff98b206d55428aee0dc276efe54f100899c7fa8ab7 - languageName: node - linkType: hard - "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -3967,24 +3693,6 @@ __metadata: languageName: node linkType: hard -"simple-concat@npm:^1.0.0": - version: 1.0.1 - resolution: "simple-concat@npm:1.0.1" - checksum: 4d211042cc3d73a718c21ac6c4e7d7a0363e184be6a5ad25c8a1502e49df6d0a0253979e3d50dbdd3f60ef6c6c58d756b5d66ac1e05cda9cacd2e9fc59e3876a - languageName: node - linkType: hard - -"simple-get@npm:^4.0.0": - version: 4.0.1 - resolution: "simple-get@npm:4.0.1" - dependencies: - decompress-response: ^6.0.0 - once: ^1.3.1 - simple-concat: ^1.0.0 - checksum: e4132fd27cf7af230d853fa45c1b8ce900cb430dd0a3c6d3829649fe4f2b26574c803698076c4006450efb0fad2ba8c5455fbb5755d4b0a5ec42d4f12b31d27e - languageName: node - linkType: hard - "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -4109,13 +3817,6 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:~2.0.1": - version: 2.0.1 - resolution: "strip-json-comments@npm:2.0.1" - checksum: 1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 - languageName: node - linkType: hard - "strip-literal@npm:^2.0.0": version: 2.1.0 resolution: "strip-literal@npm:2.1.0" @@ -4160,31 +3861,6 @@ __metadata: languageName: node linkType: hard -"tar-fs@npm:^2.0.0": - version: 2.1.1 - resolution: "tar-fs@npm:2.1.1" - dependencies: - chownr: ^1.1.1 - mkdirp-classic: ^0.5.2 - pump: ^3.0.0 - tar-stream: ^2.1.4 - checksum: f5b9a70059f5b2969e65f037b4e4da2daf0fa762d3d232ffd96e819e3f94665dbbbe62f76f084f1acb4dbdcce16c6e4dac08d12ffc6d24b8d76720f4d9cf032d - languageName: node - linkType: hard - -"tar-stream@npm:^2.1.4": - version: 2.2.0 - resolution: "tar-stream@npm:2.2.0" - dependencies: - bl: ^4.0.3 - end-of-stream: ^1.4.1 - fs-constants: ^1.0.0 - inherits: ^2.0.3 - readable-stream: ^3.1.1 - checksum: 699831a8b97666ef50021c767f84924cfee21c142c2eb0e79c63254e140e6408d6d55a065a2992548e72b06de39237ef2b802b99e3ece93ca3904a37622a66f3 - languageName: node - linkType: hard - "tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.1.12 resolution: "tar@npm:6.1.12" @@ -4228,7 +3904,7 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.5.1": +"tinybench@npm:^2.5.1, tinybench@npm:^2.6.0": version: 2.6.0 resolution: "tinybench@npm:2.6.0" checksum: a621ac66ac17ec5da7e9ac10b3c27040e58c3cd843ccedd8e1e3fab5702d6337b80d02b7bfbf420ab5f029dcb7895657fb80ce21181896e170fa4e6d2c2eebc4 @@ -4352,15 +4028,6 @@ __metadata: languageName: node linkType: hard -"tunnel-agent@npm:^0.6.0": - version: 0.6.0 - resolution: "tunnel-agent@npm:0.6.0" - dependencies: - safe-buffer: ^5.0.1 - checksum: 05f6510358f8afc62a057b8b692f05d70c1782b70db86d6a1e0d5e28a32389e52fa6e7707b6c5ecccacc031462e4bc35af85ecfe4bbc341767917b7cf6965711 - languageName: node - linkType: hard - "type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8"