Skip to content

Commit

Permalink
perf(591): Distinguish query metrics as sql, subscription or incremen…
Browse files Browse the repository at this point in the history
…tal update (#605)

Closes #591.
  • Loading branch information
joshua-spacetime authored Nov 28, 2023
1 parent 6e26222 commit 4bbcb4f
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 110 deletions.
6 changes: 3 additions & 3 deletions crates/core/src/db/commit_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl CommitLogMut {
let mut unwritten_commit = self.unwritten_commit.lock().unwrap();
let mut writes = Vec::with_capacity(tx_data.records.len());

let txn_type = &ctx.txn_type();
let workload = &ctx.workload();
let db = &ctx.database();
let reducer = &ctx.reducer_name().unwrap_or_default();

Expand All @@ -340,7 +340,7 @@ impl CommitLogMut {
// Increment rows inserted metric
DB_METRICS
.rdb_num_rows_inserted
.with_label_values(txn_type, db, reducer, &table_id)
.with_label_values(workload, db, reducer, &table_id)
.inc();
// Increment table rows gauge
DB_METRICS.rdb_num_table_rows.with_label_values(db, &table_id).inc();
Expand All @@ -350,7 +350,7 @@ impl CommitLogMut {
// Increment rows deleted metric
DB_METRICS
.rdb_num_rows_deleted
.with_label_values(txn_type, db, reducer, &table_id)
.with_label_values(workload, db, reducer, &table_id)
.inc();
// Decrement table rows gauge
DB_METRICS.rdb_num_table_rows.with_label_values(db, &table_id).dec();
Expand Down
38 changes: 19 additions & 19 deletions crates/core/src/db/datastore/locking_tx_datastore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::db::datastore::system_tables::{
TABLE_ID_SEQUENCE_ID, WASM_MODULE,
};
use crate::db::db_metrics::{DB_METRICS, MAX_TX_CPU_TIME};
use crate::{db::datastore::system_tables, execution_context::TransactionType};
use crate::{db::datastore::system_tables, execution_context::WorkloadType};
use crate::{
db::datastore::traits::{TxOp, TxRecord},
db::{
Expand Down Expand Up @@ -1721,7 +1721,7 @@ impl Drop for Iter<'_> {
DB_METRICS
.rdb_num_rows_fetched
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.into(),
Expand Down Expand Up @@ -1841,7 +1841,7 @@ impl Drop for IndexSeekIterInner<'_> {
DB_METRICS
.rdb_num_index_seeks
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand All @@ -1852,7 +1852,7 @@ impl Drop for IndexSeekIterInner<'_> {
DB_METRICS
.rdb_num_keys_scanned
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand All @@ -1863,7 +1863,7 @@ impl Drop for IndexSeekIterInner<'_> {
DB_METRICS
.rdb_num_rows_fetched
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand Down Expand Up @@ -1915,7 +1915,7 @@ impl Drop for CommittedIndexIter<'_> {
DB_METRICS
.rdb_num_index_seeks
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand All @@ -1926,7 +1926,7 @@ impl Drop for CommittedIndexIter<'_> {
DB_METRICS
.rdb_num_keys_scanned
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand All @@ -1937,7 +1937,7 @@ impl Drop for CommittedIndexIter<'_> {
DB_METRICS
.rdb_num_rows_fetched
.with_label_values(
&self.ctx.txn_type(),
&self.ctx.workload(),
&self.ctx.database(),
self.ctx.reducer_name().unwrap_or_default(),
&self.table_id.0,
Expand Down Expand Up @@ -2093,28 +2093,28 @@ impl traits::MutTx for Locking {
}

fn rollback_mut_tx(&self, ctx: &ExecutionContext, mut tx: Self::MutTxId) {
let txn_type = &ctx.txn_type();
let workload = &ctx.workload();
let db = &ctx.database();
let reducer = ctx.reducer_name().unwrap_or_default();
let elapsed_time = tx.timer.elapsed();
let cpu_time = elapsed_time - tx.lock_wait_time;
DB_METRICS
.rdb_num_txns
.with_label_values(txn_type, db, reducer, &false)
.with_label_values(workload, db, reducer, &false)
.inc();
DB_METRICS
.rdb_txn_cpu_time_sec
.with_label_values(txn_type, db, reducer)
.with_label_values(workload, db, reducer)
.observe(cpu_time.as_secs_f64());
DB_METRICS
.rdb_txn_elapsed_time_sec
.with_label_values(txn_type, db, reducer)
.with_label_values(workload, db, reducer)
.observe(elapsed_time.as_secs_f64());
tx.lock.rollback();
}

fn commit_mut_tx(&self, ctx: &ExecutionContext, mut tx: Self::MutTxId) -> super::Result<Option<TxData>> {
let txn_type = &ctx.txn_type();
let workload = &ctx.workload();
let db = &ctx.database();
let reducer = ctx.reducer_name().unwrap_or_default();
let elapsed_time = tx.timer.elapsed();
Expand All @@ -2126,18 +2126,18 @@ impl traits::MutTx for Locking {
// That is, transactions that don't write any rows to the commit log.
DB_METRICS
.rdb_num_txns
.with_label_values(txn_type, db, reducer, &true)
.with_label_values(workload, db, reducer, &true)
.inc();
DB_METRICS
.rdb_txn_cpu_time_sec
.with_label_values(txn_type, db, reducer)
.with_label_values(workload, db, reducer)
.observe(cpu_time);
DB_METRICS
.rdb_txn_elapsed_time_sec
.with_label_values(txn_type, db, reducer)
.with_label_values(workload, db, reducer)
.observe(elapsed_time);

fn hash(a: &TransactionType, b: &Address, c: &str) -> u64 {
fn hash(a: &WorkloadType, b: &Address, c: &str) -> u64 {
use std::hash::Hash;
let mut hasher = DefaultHasher::new();
a.hash(&mut hasher);
Expand All @@ -2148,7 +2148,7 @@ impl traits::MutTx for Locking {

let mut guard = MAX_TX_CPU_TIME.lock().unwrap();
let max_cpu_time = *guard
.entry(hash(txn_type, db, reducer))
.entry(hash(workload, db, reducer))
.and_modify(|max| {
if cpu_time > *max {
*max = cpu_time;
Expand All @@ -2159,7 +2159,7 @@ impl traits::MutTx for Locking {
drop(guard);
DB_METRICS
.rdb_txn_cpu_time_sec_max
.with_label_values(txn_type, db, reducer)
.with_label_values(workload, db, reducer)
.set(max_cpu_time);

tx.lock.commit()
Expand Down
22 changes: 11 additions & 11 deletions crates/core/src/db/db_metrics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, sync::Mutex};

use crate::{execution_context::TransactionType, host::AbiCall, util::typed_prometheus::metrics_group};
use crate::{execution_context::WorkloadType, host::AbiCall, util::typed_prometheus::metrics_group};
use once_cell::sync::Lazy;
use prometheus::{GaugeVec, Histogram, HistogramVec, IntCounterVec, IntGaugeVec};
use spacetimedb_lib::Address;
Expand Down Expand Up @@ -60,52 +60,52 @@ metrics_group!(

#[name = spacetime_num_rows_inserted_cumulative]
#[help = "The cumulative number of rows inserted into a table"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, table_id: u32)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, table_id: u32)]
pub rdb_num_rows_inserted: IntCounterVec,

#[name = spacetime_num_rows_deleted_cumulative]
#[help = "The cumulative number of rows deleted from a table"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, table_id: u32)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, table_id: u32)]
pub rdb_num_rows_deleted: IntCounterVec,

#[name = spacetime_num_rows_fetched_cumulative]
#[help = "The cumulative number of rows fetched from a table"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, table_id: u32)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, table_id: u32)]
pub rdb_num_rows_fetched: IntCounterVec,

#[name = spacetime_num_index_keys_scanned_cumulative]
#[help = "The cumulative number of keys scanned from an index"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, table_id: u32)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, table_id: u32)]
pub rdb_num_keys_scanned: IntCounterVec,

#[name = spacetime_num_index_seeks_cumulative]
#[help = "The cumulative number of index seeks"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, table_id: u32)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, table_id: u32)]
pub rdb_num_index_seeks: IntCounterVec,

#[name = spacetime_num_txns_cumulative]
#[help = "The cumulative number of transactions, including both commits and rollbacks"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, committed: bool)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, committed: bool)]
pub rdb_num_txns: IntCounterVec,

#[name = spacetime_txn_elapsed_time_sec]
#[help = "The total elapsed (wall) time of a transaction (in seconds)"]
#[labels(txn_type: TransactionType, db: Address, reducer: str)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str)]
pub rdb_txn_elapsed_time_sec: HistogramVec,

#[name = spacetime_txn_cpu_time_sec]
#[help = "The time spent executing a transaction (in seconds), excluding time spent waiting to acquire database locks"]
#[labels(txn_type: TransactionType, db: Address, reducer: str)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str)]
pub rdb_txn_cpu_time_sec: HistogramVec,

#[name = spacetime_txn_cpu_time_sec_max]
#[help = "The cpu time of the longest running transaction (in seconds)"]
#[labels(txn_type: TransactionType, db: Address, reducer: str)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str)]
pub rdb_txn_cpu_time_sec_max: GaugeVec,

#[name = spacetime_wasm_abi_call_duration_sec]
#[help = "The total duration of a spacetime wasm abi call (in seconds); includes row serialization and copying into wasm memory"]
#[labels(txn_type: TransactionType, db: Address, reducer: str, call: AbiCall)]
#[labels(txn_type: WorkloadType, db: Address, reducer: str, call: AbiCall)]
pub wasm_abi_call_duration_sec: HistogramVec,

#[name = spacetime_message_log_size_bytes]
Expand Down
48 changes: 35 additions & 13 deletions crates/core/src/execution_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,28 @@ pub struct ExecutionContext<'a> {
reducer: Option<&'a str>,
/// The SQL query being executed, if any.
/// Note: this will never be set at the same time as `reducer`.
/// It is also NOT guaranteed to be set, even if txn_type == Sql.
/// It is also NOT guaranteed to be set, even if workload == Sql.
/// This is because some transactions tagged "SQL" don't exactly correspond
/// to any particular query.
query_debug_info: Option<&'a QueryDebugInfo>,
// The type of transaction that is being executed.
txn_type: TransactionType,
// The type of workload that is being executed.
workload: WorkloadType,
}

/// Classifies a transaction according to where it originates.
/// Classifies a transaction according to its workload.
/// A transaction can be executing a reducer.
/// It can be used to satisfy a one-off sql query or subscription.
/// It can also be an internal operation that is not associated with a reducer or sql request.
#[derive(Clone, Copy, Display, Hash, PartialEq, Eq)]
pub enum TransactionType {
pub enum WorkloadType {
Reducer,
Sql,
Subscribe,
Update,
Internal,
}

impl Default for TransactionType {
impl Default for WorkloadType {
fn default() -> Self {
Self::Internal
}
Expand All @@ -47,17 +49,37 @@ impl<'a> ExecutionContext<'a> {
database,
reducer: Some(name),
query_debug_info: None,
txn_type: TransactionType::Reducer,
workload: WorkloadType::Reducer,
}
}

/// Returns an [ExecutionContext] for a sql or subscription transaction.
/// Returns an [ExecutionContext] for a one-off sql query.
pub fn sql(database: Address, query_debug_info: Option<&'a QueryDebugInfo>) -> Self {
Self {
database,
reducer: None,
query_debug_info,
txn_type: TransactionType::Sql,
workload: WorkloadType::Sql,
}
}

/// Returns an [ExecutionContext] for an initial subscribe call.
pub fn subscribe(database: Address, query_debug_info: Option<&'a QueryDebugInfo>) -> Self {
Self {
database,
reducer: None,
query_debug_info,
workload: WorkloadType::Subscribe,
}
}

/// Returns an [ExecutionContext] for a subscription update.
pub fn incremental_update(database: Address, query_debug_info: Option<&'a QueryDebugInfo>) -> Self {
Self {
database,
reducer: None,
query_debug_info,
workload: WorkloadType::Update,
}
}

Expand All @@ -67,7 +89,7 @@ impl<'a> ExecutionContext<'a> {
database,
reducer: None,
query_debug_info: None,
txn_type: TransactionType::Internal,
workload: WorkloadType::Internal,
}
}

Expand All @@ -91,9 +113,9 @@ impl<'a> ExecutionContext<'a> {
self.query_debug_info
}

/// Returns the type of transaction that is being executed.
/// Returns the type of workload that is being executed.
#[inline]
pub fn txn_type(&self) -> TransactionType {
self.txn_type
pub fn workload(&self) -> WorkloadType {
self.workload
}
}
4 changes: 2 additions & 2 deletions crates/core/src/host/wasmtime/wasm_instance_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,12 @@ impl WasmInstanceEnv {
/// Gather the appropriate metadata and log a wasm_abi_call_duration_ns with the given AbiCall & duration
fn start_abi_call_timer(&self, call: AbiCall) -> prometheus::HistogramTimer {
let ctx = self.reducer_context();
let txn_type = ctx.txn_type();
let workload = ctx.workload();
let db = ctx.database();

DB_METRICS
.wasm_abi_call_duration_sec
.with_label_values(&txn_type, &db, &self.reducer_name, &call)
.with_label_values(&workload, &db, &self.reducer_name, &call)
.start_timer()
}

Expand Down
7 changes: 3 additions & 4 deletions crates/core/src/sql/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,15 @@ fn collect_result(result: &mut Vec<MemTable>, r: CodeResult) -> Result<(), DBErr
Ok(())
}

#[tracing::instrument(skip(db, tx, auth))]
#[tracing::instrument(skip_all)]
pub fn execute_single_sql(
cx: &ExecutionContext,
db: &RelationalDB,
tx: &mut MutTxId,
ast: CrudExpr,
query_debug_info: Option<&QueryDebugInfo>,
auth: AuthCtx,
) -> Result<Vec<MemTable>, DBError> {
let ctx = ExecutionContext::sql(db.address(), query_debug_info);
let p = &mut DbProgram::new(&ctx, db, tx, auth);
let p = &mut DbProgram::new(cx, db, tx, auth);
let q = Expr::Crud(Box::new(ast));

let mut result = Vec::with_capacity(1);
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/subscription/module_subscription_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl ModuleSubscriptionActor {

// Note: the missing QueryDebugInfo here is only used for finishing the transaction;
// all of the relevant queries already executed, with debug info, in _add_subscription
let ctx = ExecutionContext::sql(self.relational_db.address(), None);
let ctx = ExecutionContext::subscribe(self.relational_db.address(), None);
self.relational_db.finish_tx(&ctx, tx, result)
}

Expand Down Expand Up @@ -218,7 +218,7 @@ impl ModuleSubscriptionActor {
//Split logic to properly handle `Error` + `Tx`
let mut tx = self.relational_db.begin_tx();
let result = self._broadcast_commit_event(event, &mut tx).await;
let ctx = ExecutionContext::sql(self.relational_db.address(), None);
let ctx = ExecutionContext::incremental_update(self.relational_db.address(), None);
self.relational_db.finish_tx(&ctx, tx, result)
}
}
Loading

1 comment on commit 4bbcb4f

@github-actions
Copy link

@github-actions github-actions bot commented on 4bbcb4f Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark results

Benchmark Report

Legend:

  • load: number of rows pre-loaded into the database
  • count: number of rows touched by the transaction
  • index types:
    • unique: a single index on the id column
    • non_unique: no indexes
    • multi_index: non-unique index on every column
  • schemas:
    • person(id: u32, name: String, age: u64)
    • location(id: u32, x: u64, y: u64)

All throughputs are single-threaded.

Empty transaction

db on disk new latency old latency new throughput old throughput
sqlite 💿 437.7±2.92ns 430.7±1.63ns - -
sqlite 🧠 427.6±7.65ns 424.9±2.80ns - -
stdb_module 💿 16.9±0.38µs 17.4±1.08µs - -
stdb_module 🧠 17.5±0.96µs 18.3±1.31µs - -
stdb_raw 💿 911.9±1.28ns 912.4±1.35ns - -
stdb_raw 🧠 867.4±1.32ns 871.5±0.84ns - -

Single-row insertions

db on disk schema index type load new latency old latency new throughput old throughput
sqlite 💿 location multi_index 0 14.7±0.78µs 14.8±1.67µs 66.3 Ktx/sec 65.9 Ktx/sec
sqlite 💿 location multi_index 1000 15.7±0.16µs 17.4±16.44µs 62.1 Ktx/sec 56.1 Ktx/sec
sqlite 💿 location non_unique 0 7.2±0.31µs 7.2±0.04µs 134.7 Ktx/sec 135.8 Ktx/sec
sqlite 💿 location non_unique 1000 7.1±0.05µs 7.1±0.03µs 136.8 Ktx/sec 137.4 Ktx/sec
sqlite 💿 location unique 0 7.2±0.03µs 7.1±0.03µs 136.3 Ktx/sec 136.7 Ktx/sec
sqlite 💿 location unique 1000 7.1±0.03µs 7.1±0.04µs 136.8 Ktx/sec 136.8 Ktx/sec
sqlite 💿 person multi_index 0 14.3±0.04µs 14.3±0.02µs 68.2 Ktx/sec 68.3 Ktx/sec
sqlite 💿 person multi_index 1000 16.2±0.13µs 16.0±0.11µs 60.3 Ktx/sec 61.2 Ktx/sec
sqlite 💿 person non_unique 0 7.3±0.50µs 7.3±0.42µs 133.7 Ktx/sec 133.0 Ktx/sec
sqlite 💿 person non_unique 1000 7.3±0.04µs 7.4±0.05µs 133.9 Ktx/sec 131.8 Ktx/sec
sqlite 💿 person unique 0 7.3±0.03µs 7.3±0.03µs 134.3 Ktx/sec 134.0 Ktx/sec
sqlite 💿 person unique 1000 7.4±0.04µs 7.3±0.06µs 132.3 Ktx/sec 133.4 Ktx/sec
sqlite 🧠 location multi_index 0 3.9±0.01µs 4.0±0.01µs 247.4 Ktx/sec 244.4 Ktx/sec
sqlite 🧠 location multi_index 1000 5.1±0.04µs 5.2±0.05µs 191.1 Ktx/sec 187.3 Ktx/sec
sqlite 🧠 location non_unique 0 1851.8±3.89ns 1854.8±4.15ns 527.4 Ktx/sec 526.5 Ktx/sec
sqlite 🧠 location non_unique 1000 1865.9±5.60ns 1908.7±9.73ns 523.4 Ktx/sec 511.6 Ktx/sec
sqlite 🧠 location unique 0 1831.2±4.72ns 1839.5±5.47ns 533.3 Ktx/sec 530.9 Ktx/sec
sqlite 🧠 location unique 1000 1925.1±13.93ns 1953.0±9.95ns 507.3 Ktx/sec 500.0 Ktx/sec
sqlite 🧠 person multi_index 0 3.6±0.01µs 3.7±0.01µs 270.4 Ktx/sec 267.1 Ktx/sec
sqlite 🧠 person multi_index 1000 5.5±0.05µs 5.5±0.04µs 176.2 Ktx/sec 177.5 Ktx/sec
sqlite 🧠 person non_unique 0 1930.0±4.67ns 1926.4±17.50ns 506.0 Ktx/sec 506.9 Ktx/sec
sqlite 🧠 person non_unique 1000 1999.3±13.01ns 1990.4±12.40ns 488.5 Ktx/sec 490.6 Ktx/sec
sqlite 🧠 person unique 0 1900.3±7.81ns 1921.2±12.94ns 513.9 Ktx/sec 508.3 Ktx/sec
sqlite 🧠 person unique 1000 2.1±0.02µs 2.0±0.01µs 475.7 Ktx/sec 482.6 Ktx/sec
stdb_module 💿 location multi_index 0 52.4±4.95µs 52.9±5.61µs 18.6 Ktx/sec 18.5 Ktx/sec
stdb_module 💿 location multi_index 1000 312.5±18.00µs 166.7±4.53µs 3.1 Ktx/sec 5.9 Ktx/sec
stdb_module 💿 location non_unique 0 44.2±4.47µs 40.4±3.56µs 22.1 Ktx/sec 24.2 Ktx/sec
stdb_module 💿 location non_unique 1000 282.4±2.69µs 284.8±22.73µs 3.5 Ktx/sec 3.4 Ktx/sec
stdb_module 💿 location unique 0 46.8±4.88µs 47.4±4.84µs 20.9 Ktx/sec 20.6 Ktx/sec
stdb_module 💿 location unique 1000 268.1±65.17µs 225.1±52.99µs 3.6 Ktx/sec 4.3 Ktx/sec
stdb_module 💿 person multi_index 0 69.6±5.02µs 66.2±3.37µs 14.0 Ktx/sec 14.8 Ktx/sec
stdb_module 💿 person multi_index 1000 340.1±18.42µs 367.4±21.69µs 2.9 Ktx/sec 2.7 Ktx/sec
stdb_module 💿 person non_unique 0 46.2±4.64µs 48.8±4.11µs 21.1 Ktx/sec 20.0 Ktx/sec
stdb_module 💿 person non_unique 1000 331.7±22.79µs 138.8±41.15µs 2.9 Ktx/sec 7.0 Ktx/sec
stdb_module 💿 person unique 0 55.1±4.67µs 56.3±5.95µs 17.7 Ktx/sec 17.3 Ktx/sec
stdb_module 💿 person unique 1000 203.5±96.00µs 201.1±103.62µs 4.8 Ktx/sec 4.9 Ktx/sec
stdb_module 🧠 location multi_index 0 35.4±3.08µs 36.9±4.01µs 27.6 Ktx/sec 26.4 Ktx/sec
stdb_module 🧠 location multi_index 1000 219.3±12.60µs 119.7±8.13µs 4.5 Ktx/sec 8.2 Ktx/sec
stdb_module 🧠 location non_unique 0 29.7±2.19µs 28.1±2.06µs 32.8 Ktx/sec 34.7 Ktx/sec
stdb_module 🧠 location non_unique 1000 177.8±30.10µs 203.0±10.23µs 5.5 Ktx/sec 4.8 Ktx/sec
stdb_module 🧠 location unique 0 33.3±2.64µs 34.0±3.49µs 29.4 Ktx/sec 28.8 Ktx/sec
stdb_module 🧠 location unique 1000 190.6±5.27µs 117.3±9.12µs 5.1 Ktx/sec 8.3 Ktx/sec
stdb_module 🧠 person multi_index 0 46.1±5.16µs 43.9±4.43µs 21.2 Ktx/sec 22.2 Ktx/sec
stdb_module 🧠 person multi_index 1000 135.4±12.11µs 201.1±11.06µs 7.2 Ktx/sec 4.9 Ktx/sec
stdb_module 🧠 person non_unique 0 33.3±2.69µs 32.4±2.88µs 29.4 Ktx/sec 30.1 Ktx/sec
stdb_module 🧠 person non_unique 1000 240.7±6.38µs 240.1±10.47µs 4.1 Ktx/sec 4.1 Ktx/sec
stdb_module 🧠 person unique 0 39.9±3.55µs 37.2±2.73µs 24.5 Ktx/sec 26.2 Ktx/sec
stdb_module 🧠 person unique 1000 208.1±1.90µs 187.0±3.42µs 4.7 Ktx/sec 5.2 Ktx/sec
stdb_raw 💿 location multi_index 0 6.9±0.04µs 6.9±0.02µs 141.6 Ktx/sec 141.7 Ktx/sec
stdb_raw 💿 location multi_index 1000 29.0±195.75µs 34.8±252.95µs 33.6 Ktx/sec 28.1 Ktx/sec
stdb_raw 💿 location non_unique 0 4.5±0.01µs 4.5±0.01µs 215.7 Ktx/sec 217.1 Ktx/sec
stdb_raw 💿 location non_unique 1000 6.0±0.18µs 5.9±0.13µs 163.9 Ktx/sec 165.9 Ktx/sec
stdb_raw 💿 location unique 0 5.8±0.01µs 5.9±0.34µs 168.1 Ktx/sec 164.1 Ktx/sec
stdb_raw 💿 location unique 1000 26.0±179.31µs 8.3±0.13µs 37.6 Ktx/sec 118.3 Ktx/sec
stdb_raw 💿 person multi_index 0 11.1±0.03µs 11.1±0.02µs 87.7 Ktx/sec 88.1 Ktx/sec
stdb_raw 💿 person multi_index 1000 14.4±0.20µs 14.4±0.17µs 67.8 Ktx/sec 67.7 Ktx/sec
stdb_raw 💿 person non_unique 0 5.6±0.03µs 5.6±0.04µs 174.2 Ktx/sec 173.5 Ktx/sec
stdb_raw 💿 person non_unique 1000 7.4±0.20µs 22.8±156.24µs 132.1 Ktx/sec 42.8 Ktx/sec
stdb_raw 💿 person unique 0 8.0±0.05µs 8.0±0.02µs 121.3 Ktx/sec 121.6 Ktx/sec
stdb_raw 💿 person unique 1000 38.4±277.93µs 38.3±275.84µs 25.4 Ktx/sec 25.5 Ktx/sec
stdb_raw 🧠 location multi_index 0 4.3±0.01µs 4.3±0.01µs 225.3 Ktx/sec 225.1 Ktx/sec
stdb_raw 🧠 location multi_index 1000 5.9±0.05µs 5.9±0.05µs 165.2 Ktx/sec 165.1 Ktx/sec
stdb_raw 🧠 location non_unique 0 2.1±0.00µs 2.1±0.01µs 464.6 Ktx/sec 463.8 Ktx/sec
stdb_raw 🧠 location non_unique 1000 2.6±0.02µs 2.6±0.03µs 373.6 Ktx/sec 375.8 Ktx/sec
stdb_raw 🧠 location unique 0 3.3±0.03µs 3.4±0.01µs 294.3 Ktx/sec 291.2 Ktx/sec
stdb_raw 🧠 location unique 1000 4.6±0.03µs 4.6±0.05µs 213.5 Ktx/sec 212.1 Ktx/sec
stdb_raw 🧠 person multi_index 0 8.1±0.01µs 8.1±0.02µs 120.8 Ktx/sec 121.0 Ktx/sec
stdb_raw 🧠 person multi_index 1000 10.2±0.05µs 10.1±0.10µs 95.6 Ktx/sec 96.3 Ktx/sec
stdb_raw 🧠 person non_unique 0 2.7±0.00µs 2.7±0.01µs 366.8 Ktx/sec 364.9 Ktx/sec
stdb_raw 🧠 person non_unique 1000 3.4±0.05µs 3.4±0.02µs 287.8 Ktx/sec 287.6 Ktx/sec
stdb_raw 🧠 person unique 0 5.0±0.01µs 5.0±0.02µs 196.4 Ktx/sec 195.8 Ktx/sec
stdb_raw 🧠 person unique 1000 6.5±0.03µs 6.5±0.04µs 149.2 Ktx/sec 151.3 Ktx/sec

Multi-row insertions

db on disk schema index type load count new latency old latency new throughput old throughput
sqlite 💿 location multi_index 0 100 130.8±5.51µs 130.4±0.64µs 7.5 Ktx/sec 7.5 Ktx/sec
sqlite 💿 location multi_index 1000 100 205.1±27.42µs 201.3±3.32µs 4.8 Ktx/sec 4.9 Ktx/sec
sqlite 💿 location non_unique 0 100 50.0±1.88µs 49.4±1.43µs 19.5 Ktx/sec 19.8 Ktx/sec
sqlite 💿 location non_unique 1000 100 53.0±0.29µs 51.3±0.22µs 18.4 Ktx/sec 19.0 Ktx/sec
sqlite 💿 location unique 0 100 51.7±1.87µs 51.8±2.15µs 18.9 Ktx/sec 18.9 Ktx/sec
sqlite 💿 location unique 1000 100 55.8±0.35µs 56.6±12.11µs 17.5 Ktx/sec 17.3 Ktx/sec
sqlite 💿 person multi_index 0 100 118.2±0.89µs 120.3±3.27µs 8.3 Ktx/sec 8.1 Ktx/sec
sqlite 💿 person multi_index 1000 100 233.5±2.52µs 228.0±0.45µs 4.2 Ktx/sec 4.3 Ktx/sec
sqlite 💿 person non_unique 0 100 48.5±0.90µs 49.4±0.38µs 20.1 Ktx/sec 19.8 Ktx/sec
sqlite 💿 person non_unique 1000 100 60.2±0.28µs 60.8±0.38µs 16.2 Ktx/sec 16.1 Ktx/sec
sqlite 💿 person unique 0 100 49.7±3.19µs 52.2±3.62µs 19.6 Ktx/sec 18.7 Ktx/sec
sqlite 💿 person unique 1000 100 55.6±0.29µs 55.8±0.70µs 17.6 Ktx/sec 17.5 Ktx/sec
sqlite 🧠 location multi_index 0 100 118.5±0.29µs 119.7±0.36µs 8.2 Ktx/sec 8.2 Ktx/sec
sqlite 🧠 location multi_index 1000 100 170.4±0.30µs 169.5±0.50µs 5.7 Ktx/sec 5.8 Ktx/sec
sqlite 🧠 location non_unique 0 100 44.0±0.20µs 43.3±0.20µs 22.2 Ktx/sec 22.5 Ktx/sec
sqlite 🧠 location non_unique 1000 100 45.4±0.55µs 44.2±0.40µs 21.5 Ktx/sec 22.1 Ktx/sec
sqlite 🧠 location unique 0 100 45.0±0.32µs 46.0±0.42µs 21.7 Ktx/sec 21.2 Ktx/sec
sqlite 🧠 location unique 1000 100 49.2±0.22µs 48.3±0.42µs 19.9 Ktx/sec 20.2 Ktx/sec
sqlite 🧠 person multi_index 0 100 107.1±0.48µs 107.2±0.47µs 9.1 Ktx/sec 9.1 Ktx/sec
sqlite 🧠 person multi_index 1000 100 190.9±0.35µs 189.2±0.66µs 5.1 Ktx/sec 5.2 Ktx/sec
sqlite 🧠 person non_unique 0 100 42.7±0.53µs 42.7±0.37µs 22.9 Ktx/sec 22.8 Ktx/sec
sqlite 🧠 person non_unique 1000 100 46.7±0.55µs 45.9±0.43µs 20.9 Ktx/sec 21.3 Ktx/sec
sqlite 🧠 person unique 0 100 44.1±0.21µs 44.7±0.36µs 22.1 Ktx/sec 21.8 Ktx/sec
sqlite 🧠 person unique 1000 100 48.8±0.30µs 48.5±0.23µs 20.0 Ktx/sec 20.2 Ktx/sec
stdb_module 💿 location multi_index 0 100 551.0±0.85µs 778.3±16.19µs 1814 tx/sec 1284 tx/sec
stdb_module 💿 location multi_index 1000 100 1017.6±90.36µs 878.2±10.13µs 982 tx/sec 1138 tx/sec
stdb_module 💿 location non_unique 0 100 467.0±13.81µs 401.8±2.68µs 2.1 Ktx/sec 2.4 Ktx/sec
stdb_module 💿 location non_unique 1000 100 670.9±18.59µs 455.6±4.60µs 1490 tx/sec 2.1 Ktx/sec
stdb_module 💿 location unique 0 100 577.2±65.30µs 621.3±8.28µs 1732 tx/sec 1609 tx/sec
stdb_module 💿 location unique 1000 100 744.2±51.52µs 621.3±66.40µs 1343 tx/sec 1609 tx/sec
stdb_module 💿 person multi_index 0 100 989.8±231.67µs 1004.8±5.17µs 1010 tx/sec 995 tx/sec
stdb_module 💿 person multi_index 1000 100 1068.9±43.63µs 1346.5±44.57µs 935 tx/sec 742 tx/sec
stdb_module 💿 person non_unique 0 100 763.0±9.02µs 727.6±1.90µs 1310 tx/sec 1374 tx/sec
stdb_module 💿 person non_unique 1000 100 934.5±133.55µs 867.7±98.39µs 1070 tx/sec 1152 tx/sec
stdb_module 💿 person unique 0 100 763.4±1.32µs 739.7±31.54µs 1309 tx/sec 1351 tx/sec
stdb_module 💿 person unique 1000 100 1037.4±60.15µs 969.2±38.43µs 963 tx/sec 1031 tx/sec
stdb_module 🧠 location multi_index 0 100 624.6±117.49µs 534.0±54.25µs 1600 tx/sec 1872 tx/sec
stdb_module 🧠 location multi_index 1000 100 742.7±63.27µs 732.9±94.76µs 1346 tx/sec 1364 tx/sec
stdb_module 🧠 location non_unique 0 100 376.2±10.42µs 365.3±22.10µs 2.6 Ktx/sec 2.7 Ktx/sec
stdb_module 🧠 location non_unique 1000 100 454.3±18.03µs 371.8±3.37µs 2.1 Ktx/sec 2.6 Ktx/sec
stdb_module 🧠 location unique 0 100 495.7±83.51µs 475.8±78.54µs 2017 tx/sec 2.1 Ktx/sec
stdb_module 🧠 location unique 1000 100 637.9±65.40µs 598.7±89.92µs 1567 tx/sec 1670 tx/sec
stdb_module 🧠 person multi_index 0 100 950.6±31.71µs 881.3±59.74µs 1051 tx/sec 1134 tx/sec
stdb_module 🧠 person multi_index 1000 100 978.3±10.21µs 1026.8±6.81µs 1022 tx/sec 973 tx/sec
stdb_module 🧠 person non_unique 0 100 467.3±72.50µs 385.6±0.84µs 2.1 Ktx/sec 2.5 Ktx/sec
stdb_module 🧠 person non_unique 1000 100 474.8±69.55µs 507.3±16.72µs 2.1 Ktx/sec 1971 tx/sec
stdb_module 🧠 person unique 0 100 599.7±4.53µs 620.2±5.81µs 1667 tx/sec 1612 tx/sec
stdb_module 🧠 person unique 1000 100 665.7±4.05µs 763.2±2.92µs 1502 tx/sec 1310 tx/sec
stdb_raw 💿 location multi_index 0 100 342.6±0.53µs 348.5±32.84µs 2.9 Ktx/sec 2.8 Ktx/sec
stdb_raw 💿 location multi_index 1000 100 367.4±1.49µs 395.3±271.44µs 2.7 Ktx/sec 2.5 Ktx/sec
stdb_raw 💿 location non_unique 0 100 119.5±0.23µs 120.4±0.12µs 8.2 Ktx/sec 8.1 Ktx/sec
stdb_raw 💿 location non_unique 1000 100 121.3±0.95µs 122.4±1.13µs 8.0 Ktx/sec 8.0 Ktx/sec
stdb_raw 💿 location unique 0 100 241.8±0.28µs 251.2±0.29µs 4.0 Ktx/sec 3.9 Ktx/sec
stdb_raw 💿 location unique 1000 100 261.4±1.30µs 270.0±1.17µs 3.7 Ktx/sec 3.6 Ktx/sec
stdb_raw 💿 person multi_index 0 100 712.1±2.27µs 710.3±1.02µs 1404 tx/sec 1407 tx/sec
stdb_raw 💿 person multi_index 1000 100 791.1±487.72µs 754.8±142.11µs 1264 tx/sec 1324 tx/sec
stdb_raw 💿 person non_unique 0 100 223.3±0.89µs 218.9±0.28µs 4.4 Ktx/sec 4.5 Ktx/sec
stdb_raw 💿 person non_unique 1000 100 225.7±0.31µs 221.3±0.38µs 4.3 Ktx/sec 4.4 Ktx/sec
stdb_raw 💿 person unique 0 100 430.3±0.55µs 437.8±0.96µs 2.3 Ktx/sec 2.2 Ktx/sec
stdb_raw 💿 person unique 1000 100 449.8±1.43µs 454.1±0.80µs 2.2 Ktx/sec 2.2 Ktx/sec
stdb_raw 🧠 location multi_index 0 100 298.3±0.58µs 298.4±0.73µs 3.3 Ktx/sec 3.3 Ktx/sec
stdb_raw 🧠 location multi_index 1000 100 325.5±0.51µs 323.0±0.72µs 3.0 Ktx/sec 3.0 Ktx/sec
stdb_raw 🧠 location non_unique 0 100 77.4±0.24µs 75.8±0.10µs 12.6 Ktx/sec 12.9 Ktx/sec
stdb_raw 🧠 location non_unique 1000 100 78.4±0.17µs 77.1±0.19µs 12.5 Ktx/sec 12.7 Ktx/sec
stdb_raw 🧠 location unique 0 100 198.9±0.24µs 206.5±0.33µs 4.9 Ktx/sec 4.7 Ktx/sec
stdb_raw 🧠 location unique 1000 100 217.4±0.20µs 224.7±0.29µs 4.5 Ktx/sec 4.3 Ktx/sec
stdb_raw 🧠 person multi_index 0 100 623.0±0.53µs 617.1±0.97µs 1605 tx/sec 1620 tx/sec
stdb_raw 🧠 person multi_index 1000 100 651.7±0.53µs 647.5±0.68µs 1534 tx/sec 1544 tx/sec
stdb_raw 🧠 person non_unique 0 100 132.8±0.24µs 127.9±0.49µs 7.4 Ktx/sec 7.6 Ktx/sec
stdb_raw 🧠 person non_unique 1000 100 134.9±0.16µs 129.8±0.33µs 7.2 Ktx/sec 7.5 Ktx/sec
stdb_raw 🧠 person unique 0 100 338.9±0.22µs 343.3±0.38µs 2.9 Ktx/sec 2.8 Ktx/sec
stdb_raw 🧠 person unique 1000 100 357.9±0.62µs 363.6±0.43µs 2.7 Ktx/sec 2.7 Ktx/sec

Full table iterate

db on disk schema index type new latency old latency new throughput old throughput
sqlite 💿 location unique 9.3±0.10µs 8.9±0.16µs 105.4 Ktx/sec 109.5 Ktx/sec
sqlite 💿 person unique 10.1±0.08µs 9.4±0.11µs 96.8 Ktx/sec 104.3 Ktx/sec
sqlite 🧠 location unique 8.0±0.09µs 7.6±0.10µs 121.6 Ktx/sec 128.0 Ktx/sec
sqlite 🧠 person unique 8.6±0.06µs 8.1±0.10µs 113.8 Ktx/sec 120.8 Ktx/sec
stdb_module 💿 location unique 48.1±4.96µs 49.6±3.43µs 20.3 Ktx/sec 19.7 Ktx/sec
stdb_module 💿 person unique 56.6±9.08µs 59.3±9.04µs 17.3 Ktx/sec 16.5 Ktx/sec
stdb_module 🧠 location unique 45.0±4.53µs 51.4±4.29µs 21.7 Ktx/sec 19.0 Ktx/sec
stdb_module 🧠 person unique 52.0±10.38µs 60.3±4.57µs 18.8 Ktx/sec 16.2 Ktx/sec
stdb_raw 💿 location unique 9.3±0.57µs 9.4±0.40µs 104.6 Ktx/sec 104.2 Ktx/sec
stdb_raw 💿 person unique 9.2±0.00µs 9.3±0.01µs 106.5 Ktx/sec 105.2 Ktx/sec
stdb_raw 🧠 location unique 9.1±0.02µs 9.2±0.01µs 107.1 Ktx/sec 105.8 Ktx/sec
stdb_raw 🧠 person unique 9.1±0.10µs 9.3±0.27µs 106.9 Ktx/sec 105.2 Ktx/sec

Find unique key

db on disk key type load new latency old latency new throughput old throughput
sqlite 💿 u32 1000 2.4±0.01µs 2.4±0.00µs 415.0 Ktx/sec 413.9 Ktx/sec
sqlite 🧠 u32 1000 1124.4±8.81ns 1132.6±3.77ns 868.5 Ktx/sec 862.2 Ktx/sec
stdb_module 💿 u32 1000 25.4±1.79µs 23.1±1.10µs 38.5 Ktx/sec 42.3 Ktx/sec
stdb_module 🧠 u32 1000 23.8±1.94µs 23.7±1.79µs 41.1 Ktx/sec 41.1 Ktx/sec
stdb_raw 💿 u32 1000 2.1±0.00µs 2.1±0.01µs 455.0 Ktx/sec 454.4 Ktx/sec
stdb_raw 🧠 u32 1000 2.1±0.00µs 2.1±0.00µs 467.8 Ktx/sec 465.1 Ktx/sec

Filter

db on disk key type index strategy load count new latency old latency new throughput old throughput
sqlite 💿 string indexed 1000 10 5.6±0.05µs 5.6±0.02µs 173.2 Ktx/sec 173.4 Ktx/sec
sqlite 💿 string non_indexed 1000 10 52.8±1.27µs 49.8±0.60µs 18.5 Ktx/sec 19.6 Ktx/sec
sqlite 💿 u64 indexed 1000 10 5.5±0.02µs 5.4±0.02µs 179.1 Ktx/sec 180.7 Ktx/sec
sqlite 💿 u64 non_indexed 1000 10 33.5±0.38µs 33.2±0.21µs 29.1 Ktx/sec 29.4 Ktx/sec
sqlite 🧠 string indexed 1000 10 4.2±0.01µs 4.2±0.02µs 230.8 Ktx/sec 233.2 Ktx/sec
sqlite 🧠 string non_indexed 1000 10 49.8±0.10µs 47.5±0.37µs 19.6 Ktx/sec 20.5 Ktx/sec
sqlite 🧠 u64 indexed 1000 10 4.0±0.02µs 4.0±0.02µs 243.1 Ktx/sec 246.3 Ktx/sec
sqlite 🧠 u64 non_indexed 1000 10 32.2±0.36µs 31.7±0.21µs 30.4 Ktx/sec 30.8 Ktx/sec
stdb_module 💿 string indexed 1000 10 35.2±2.55µs 34.9±1.95µs 27.8 Ktx/sec 28.0 Ktx/sec
stdb_module 💿 string non_indexed 1000 10 167.4±1.34µs 169.3±5.40µs 5.8 Ktx/sec 5.8 Ktx/sec
stdb_module 💿 u64 indexed 1000 10 32.4±2.40µs 31.5±3.34µs 30.1 Ktx/sec 31.0 Ktx/sec
stdb_module 💿 u64 non_indexed 1000 10 139.4±1.04µs 139.1±1.45µs 7.0 Ktx/sec 7.0 Ktx/sec
stdb_module 🧠 string indexed 1000 10 35.7±2.28µs 34.8±2.35µs 27.3 Ktx/sec 28.0 Ktx/sec
stdb_module 🧠 string non_indexed 1000 10 161.6±1.27µs 160.2±1.71µs 6.0 Ktx/sec 6.1 Ktx/sec
stdb_module 🧠 u64 indexed 1000 10 31.4±3.03µs 31.1±2.78µs 31.1 Ktx/sec 31.4 Ktx/sec
stdb_module 🧠 u64 non_indexed 1000 10 135.3±5.20µs 132.9±1.02µs 7.2 Ktx/sec 7.3 Ktx/sec
stdb_raw 💿 string indexed 1000 10 4.5±0.01µs 4.7±0.01µs 215.8 Ktx/sec 210.0 Ktx/sec
stdb_raw 💿 string non_indexed 1000 10 135.5±0.21µs 136.6±0.22µs 7.2 Ktx/sec 7.1 Ktx/sec
stdb_raw 💿 u64 indexed 1000 10 4.4±0.01µs 4.5±0.04µs 219.9 Ktx/sec 214.7 Ktx/sec
stdb_raw 💿 u64 non_indexed 1000 10 114.1±0.58µs 114.7±0.15µs 8.6 Ktx/sec 8.5 Ktx/sec
stdb_raw 🧠 string indexed 1000 10 4.5±0.01µs 4.6±0.05µs 218.8 Ktx/sec 212.8 Ktx/sec
stdb_raw 🧠 string non_indexed 1000 10 132.7±0.50µs 132.1±1.37µs 7.4 Ktx/sec 7.4 Ktx/sec
stdb_raw 🧠 u64 indexed 1000 10 4.4±0.01µs 4.4±0.01µs 223.7 Ktx/sec 220.4 Ktx/sec
stdb_raw 🧠 u64 non_indexed 1000 10 113.9±1.55µs 114.1±0.41µs 8.6 Ktx/sec 8.6 Ktx/sec

Serialize

schema format count new latency old latency new throughput old throughput
location bsatn 100 1680.4±29.22ns 1668.2±33.65ns 56.8 Mtx/sec 57.2 Mtx/sec
location json 100 3.3±0.07µs 3.6±0.03µs 28.8 Mtx/sec 26.5 Mtx/sec
location product_value 100 571.8±1.41ns 572.3±0.68ns 166.8 Mtx/sec 166.6 Mtx/sec
person bsatn 100 2.9±0.04µs 3.0±0.05µs 33.3 Mtx/sec 31.7 Mtx/sec
person json 100 4.8±0.03µs 5.1±0.06µs 19.7 Mtx/sec 18.5 Mtx/sec
person product_value 100 1006.1±3.63ns 1031.6±1.50ns 94.8 Mtx/sec 92.4 Mtx/sec

Module: invoke with large arguments

arg size new latency old latency new throughput old throughput
64KiB 67.1±10.28µs 68.1±11.50µs - -

Module: print bulk

line count new latency old latency new throughput old throughput
1 23.8±1.97µs 23.4±1.74µs - -
100 191.6±1.20µs 194.2±6.52µs - -
1000 1802.0±492.88µs 1854.5±82.79µs - -

Remaining benchmarks

name new latency old latency new throughput old throughput

Please sign in to comment.