diff --git a/.github/workflows/crud-bench.yml b/.github/workflows/crud-bench.yml index ac9bdddc..4acda5b6 100644 --- a/.github/workflows/crud-bench.yml +++ b/.github/workflows/crud-bench.yml @@ -137,6 +137,9 @@ jobs: # MongoDB - database: mongodb description: MongoDB + # ReDB + - database: redb + description: ReDB # RocksDB - database: rocksdb description: RocksDB @@ -175,4 +178,7 @@ jobs: run: ${{ github.workspace }}/artifacts/crud-bench -d ${{ matrix.database }} -s 30000 -t 32 - name: Run benchmarks (100,000 samples / 32 threads) - run: ${{ github.workspace }}/artifacts/crud-bench -d ${{ matrix.database }} -s 100000 -t 32 \ No newline at end of file + run: ${{ github.workspace }}/artifacts/crud-bench -d ${{ matrix.database }} -s 100000 -t 32 + + - name: Run benchmarks (250,000 samples / 128 threads) + run: ${{ github.workspace }}/artifacts/crud-bench -d ${{ matrix.database }} -s 250000 -t 128 \ No newline at end of file diff --git a/crud-bench/Cargo.toml b/crud-bench/Cargo.toml index ce516d09..be5611d2 100644 --- a/crud-bench/Cargo.toml +++ b/crud-bench/Cargo.toml @@ -6,11 +6,12 @@ license = "Apache-2.0" readme = "README.md" [features] -default = ["redis", "rocksdb", "postgres", "mongodb", "surrealkv", "surrealdb"] -redis = ["dep:redis"] +default = ["redis", "redb", "rocksdb", "postgres", "mongodb", "surrealkv", "surrealdb"] mongodb = ["dep:mongodb"] -rocksdb = ["dep:rocksdb"] postgres = ["dep:tokio-postgres"] +redb = ["dep:redb"] +redis = ["dep:redis"] +rocksdb = ["dep:rocksdb"] surrealdb = ["dep:surrealdb"] surrealkv = ["dep:surrealkv"] @@ -29,6 +30,7 @@ log = "0.4.22" mongodb = { version = "2.8.2", optional = true } rand = { version = "0.8.5", features = ["small_rng"] } rayon = "1.10.0" +redb = { version = "2.1.3", optional = true } redis = { version = "0.24.0", features = ["tokio-comp"], optional = true } rocksdb = { git = "https://github.com/surrealdb/rust-rocksdb", features = ["lz4", "snappy"], optional = true } serde = { version = "1.0.210", features = ["derive"] } diff --git a/crud-bench/src/main.rs b/crud-bench/src/main.rs index c4061418..799f30a3 100644 --- a/crud-bench/src/main.rs +++ b/crud-bench/src/main.rs @@ -10,6 +10,8 @@ use crate::dry::DryClientProvider; use crate::mongodb::MongoDBClientProvider; #[cfg(feature = "postgres")] use crate::postgres::PostgresClientProvider; +#[cfg(feature = "rocksdb")] +use crate::redb::ReDBClientProvider; #[cfg(feature = "redis")] use crate::redis::RedisClientProvider; #[cfg(feature = "rocksdb")] @@ -24,6 +26,7 @@ mod docker; mod dry; mod mongodb; mod postgres; +mod redb; mod redis; mod rocksdb; mod surrealdb; @@ -56,6 +59,8 @@ pub(crate) struct Args { #[derive(ValueEnum, Debug, Clone)] pub(crate) enum Database { Dry, + #[cfg(feature = "redb")] + Redb, #[cfg(feature = "rocksdb")] Rocksdb, #[cfg(feature = "surrealkv")] @@ -80,6 +85,8 @@ impl Database { fn start_docker(&self, image: Option) -> Option { let params: DockerParams = match self { Database::Dry => return None, + #[cfg(feature = "redb")] + Database::Redb => return None, #[cfg(feature = "rocksdb")] Database::Rocksdb => return None, #[cfg(feature = "surrealkv")] @@ -107,6 +114,8 @@ impl Database { async fn run(&self, benchmark: &Benchmark) -> Result { match self { Database::Dry => benchmark.run(DryClientProvider::default()).await, + #[cfg(feature = "redb")] + Database::Redb => benchmark.run(ReDBClientProvider::setup().await?).await, #[cfg(feature = "rocksdb")] Database::Rocksdb => benchmark.run(RocksDBClientProvider::setup().await?).await, #[cfg(feature = "surrealkv")] diff --git a/crud-bench/src/redb.rs b/crud-bench/src/redb.rs new file mode 100644 index 00000000..5651316b --- /dev/null +++ b/crud-bench/src/redb.rs @@ -0,0 +1,89 @@ +#![cfg(feature = "redb")] + +use anyhow::Error; +use anyhow::Result; +use redb::{Database, TableDefinition}; +use std::sync::Arc; + +use crate::benchmark::{BenchmarkClient, BenchmarkEngine, Record}; + +const TABLE: TableDefinition<&[u8], Vec> = TableDefinition::new("test"); + +pub(crate) struct ReDBClientProvider { + db: Arc, +} + +impl ReDBClientProvider { + pub(crate) async fn setup() -> Result { + Ok(Self { + db: Arc::new(Database::create("redb")?), + }) + } +} + +impl BenchmarkEngine for ReDBClientProvider { + async fn create_client(&self, _: Option) -> Result { + Ok(ReDBClient { + db: self.db.clone(), + }) + } +} + +pub(crate) struct ReDBClient { + db: Arc, +} + +impl BenchmarkClient for ReDBClient { + async fn read(&mut self, key: i32) -> Result<()> { + let key = &key.to_ne_bytes(); + // Create a new transaction + let txn = self.db.begin_read()?; + // Open the database table + let tab = txn.open_table(TABLE)?; + // Process the data + let read: Option<_> = tab.get(key.as_ref())?; + assert!(read.is_some()); + Ok(()) + } + + async fn create(&mut self, key: i32, record: &Record) -> Result<()> { + let key = &key.to_ne_bytes(); + let val = serde_json::to_vec(record)?; + // Create a new transaction + let txn = self.db.begin_write()?; + // Open the database table + let mut tab = txn.open_table(TABLE)?; + // Process the data + tab.insert(key.as_ref(), val)?; + drop(tab); + txn.commit()?; + Ok(()) + } + + async fn update(&mut self, key: i32, record: &Record) -> Result<()> { + let key = &key.to_ne_bytes(); + let val = serde_json::to_vec(record)?; + // Create a new transaction + let txn = self.db.begin_write()?; + // Open the database table + let mut tab = txn.open_table(TABLE)?; + // Process the data + tab.insert(key.as_ref(), val)?; + drop(tab); + txn.commit()?; + Ok(()) + } + + async fn delete(&mut self, key: i32) -> Result<()> { + let key = &key.to_ne_bytes(); + // Create a new transaction + let txn = self.db.begin_write()?; + // Open the database table + let mut tab = txn.open_table(TABLE)?; + // Process the data + tab.remove(key.as_ref())?; + drop(tab); + txn.commit()?; + Ok(()) + } +}