Skip to content

Commit

Permalink
Add spacetimedb::sql::query_debug_info::QueryDebugInfo (#560)
Browse files Browse the repository at this point in the history
Add spacetimedb::sql::query_debug_info::QueryDebugInfo

---------

Signed-off-by: james gilles <jameshgilles@gmail.com>
  • Loading branch information
kazimuth authored Nov 21, 2023
1 parent 5a2b37b commit 419cfca
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 44 deletions.
25 changes: 22 additions & 3 deletions crates/core/src/execution_context.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
use derive_more::Display;
use spacetimedb_lib::Address;

use crate::sql::query_debug_info::QueryDebugInfo;

/// Represents the context under which a database runtime method is executed.
/// In particular it provides details about the currently executing txn to runtime operations.
/// More generally it acts as a container for information that database operations may require to function correctly.
#[derive(Default)]
pub struct ExecutionContext<'a> {
// The database on which a transaction is being executed.
/// The database on which a transaction is being executed.
database: Address,
// The reducer from which the current transaction originated.
/// The reducer from which the current transaction originated.
/// Note: this will never be set at the same time as `query`.
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.
/// 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,
}
Expand Down Expand Up @@ -37,15 +46,17 @@ impl<'a> ExecutionContext<'a> {
Self {
database,
reducer: Some(name),
query_debug_info: None,
txn_type: TransactionType::Reducer,
}
}

/// Returns an [ExecutionContext] for a sql or subscription transaction.
pub fn sql(database: Address) -> Self {
pub fn sql(database: Address, query_debug_info: Option<&'a QueryDebugInfo>) -> Self {
Self {
database,
reducer: None,
query_debug_info,
txn_type: TransactionType::Sql,
}
}
Expand All @@ -55,6 +66,7 @@ impl<'a> ExecutionContext<'a> {
Self {
database,
reducer: None,
query_debug_info: None,
txn_type: TransactionType::Internal,
}
}
Expand All @@ -72,6 +84,13 @@ impl<'a> ExecutionContext<'a> {
self.reducer
}

/// Returns the debug info for the query being executed.
/// Returns [None] if this is not a sql context.
#[inline]
pub fn query_debug_info(&self) -> Option<&QueryDebugInfo> {
self.query_debug_info
}

/// Returns the type of transaction that is being executed.
#[inline]
pub fn txn_type(&self) -> TransactionType {
Expand Down
34 changes: 19 additions & 15 deletions crates/core/src/host/wasm_common/module_host_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::host::{
};
use crate::identity::Identity;
use crate::sql;
use crate::sql::query_debug_info::QueryDebugInfo;
use crate::subscription::module_subscription_actor::ModuleSubscriptionManager;
use crate::util::{const_unwrap, ResultInspectExt};
use crate::worker_metrics::WORKER_METRICS;
Expand Down Expand Up @@ -249,21 +250,24 @@ impl<T: WasmModule> Module for WasmModuleHostActor<T> {
let auth = AuthCtx::new(self.database_instance_context.identity, caller_identity);
// TODO(jgilles): make this a read-only TX when those get added

db.with_read_only(&ExecutionContext::sql(db.address()), |tx| {
log::debug!("One-off query: {query}");

let compiled = sql::compiler::compile_sql(db, tx, &query)?
.into_iter()
.map(|expr| {
if matches!(expr, CrudExpr::Query { .. }) {
Ok(expr)
} else {
Err(anyhow!("One-off queries are not allowed to modify the database"))
}
})
.collect::<Result<_, _>>()?;
sql::execute::execute_sql(db, tx, compiled, auth)
})
db.with_read_only(
&ExecutionContext::sql(db.address(), Some(&QueryDebugInfo::from_source(&query))),
|tx| {
log::debug!("One-off query: {query}");

let compiled = sql::compiler::compile_sql(db, tx, &query)?
.into_iter()
.map(|expr| {
if matches!(expr, CrudExpr::Query { .. }) {
Ok(expr)
} else {
Err(anyhow!("One-off queries are not allowed to modify the database"))
}
})
.collect::<Result<_, _>>()?;
sql::execute::execute_sql(db, tx, compiled, Some(&QueryDebugInfo::from_source(&query)), auth)
},
)
}

fn clear_table(&self, table_name: String) -> Result<(), anyhow::Error> {
Expand Down
13 changes: 9 additions & 4 deletions crates/core/src/sql/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::execution_context::ExecutionContext;
use crate::sql::compiler::compile_sql;
use crate::vm::DbProgram;

use super::query_debug_info::QueryDebugInfo;

pub struct StmtResult {
pub schema: ProductType,
pub rows: Vec<ProductValue>,
Expand All @@ -32,7 +34,8 @@ pub fn execute(
info!(sql = sql_text);
if let Some((database_instance_context, _)) = db_inst_ctx_controller.get(database_instance_id) {
let db = &database_instance_context.relational_db;
let ctx = ExecutionContext::sql(db.address());
let info = QueryDebugInfo::from_source(&sql_text);
let ctx = ExecutionContext::sql(db.address(), Some(&info));
db.with_auto_commit(&ctx, |tx| {
run(&database_instance_context.relational_db, tx, &sql_text, auth)
})
Expand Down Expand Up @@ -62,9 +65,10 @@ pub fn execute_single_sql(
db: &RelationalDB,
tx: &mut MutTxId,
ast: CrudExpr,
query_debug_info: Option<&QueryDebugInfo>,
auth: AuthCtx,
) -> Result<Vec<MemTable>, DBError> {
let ctx = ExecutionContext::sql(db.address());
let ctx = ExecutionContext::sql(db.address(), query_debug_info);
let p = &mut DbProgram::new(&ctx, db, tx, auth);
let q = Expr::Crud(Box::new(ast));

Expand All @@ -79,10 +83,11 @@ pub fn execute_sql(
db: &RelationalDB,
tx: &mut MutTxId,
ast: Vec<CrudExpr>,
query_debug_info: Option<&QueryDebugInfo>,
auth: AuthCtx,
) -> Result<Vec<MemTable>, DBError> {
let total = ast.len();
let ctx = ExecutionContext::sql(db.address());
let ctx = ExecutionContext::sql(db.address(), query_debug_info);
let p = &mut DbProgram::new(&ctx, db, tx, auth);
let q = Expr::Block(ast.into_iter().map(|x| Expr::Crud(Box::new(x))).collect());

Expand All @@ -95,7 +100,7 @@ pub fn execute_sql(
#[tracing::instrument(skip_all)]
pub fn run(db: &RelationalDB, tx: &mut MutTxId, sql_text: &str, auth: AuthCtx) -> Result<Vec<MemTable>, DBError> {
let ast = compile_sql(db, tx, sql_text)?;
execute_sql(db, tx, ast, auth)
execute_sql(db, tx, ast, Some(&QueryDebugInfo::from_source(sql_text)), auth)
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/sql/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod ast;
pub mod compiler;
pub mod execute;
pub mod query_debug_info;
22 changes: 22 additions & 0 deletions crates/core/src/sql/query_debug_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::sync::Arc;

/// Used to store the source of a SQL query in a way that can be cheaply cloned,
/// without proliferating lifetimes everywhere.
///
/// TODO: if CrudExpr ever gets refactored, this should probably be attached to those.
/// That would be a large refactoring though. It would be nice if we could get
/// more precise spans from sqlparser. We could stick all sorts of other things in here too.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct QueryDebugInfo(Arc<str>);

impl QueryDebugInfo {
/// Create a new [QueryDebugInfo] from the given source text.
pub fn from_source<T: AsRef<str>>(source: T) -> Self {
Self(source.as_ref().into())
}

/// Get the source text of the query, if available.
pub fn source(&self) -> &str {
&self.0
}
}
10 changes: 7 additions & 3 deletions crates/core/src/subscription/module_subscription_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,14 @@ impl ModuleSubscriptionActor {
sender: ClientConnectionSender,
subscription: Subscribe,
) -> Result<(), DBError> {
//Split logic to properly handle `Error` + `Tx`
// Split logic to properly handle `Error` + `Tx`
let mut tx = self.relational_db.begin_tx();

let result = self._add_subscription(sender, subscription, &mut tx).await;
let ctx = ExecutionContext::sql(self.relational_db.address());

// 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);
self.relational_db.finish_tx(&ctx, tx, result)
}

Expand Down Expand Up @@ -214,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());
let ctx = ExecutionContext::sql(self.relational_db.address(), None);
self.relational_db.finish_tx(&ctx, tx, result)
}
}
18 changes: 13 additions & 5 deletions crates/core/src/subscription/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::error::{DBError, SubscriptionError};
use crate::host::module_host::DatabaseTableUpdate;
use crate::sql::compiler::compile_sql;
use crate::sql::execute::execute_single_sql;
use crate::subscription::subscription::QuerySet;
use crate::sql::query_debug_info::QueryDebugInfo;
use crate::subscription::subscription::{QuerySet, SupportedQuery};
use spacetimedb_lib::identity::AuthCtx;
use spacetimedb_sats::relation::{Column, FieldName, MemTable, RelValue};
use spacetimedb_sats::AlgebraicType;
Expand Down Expand Up @@ -69,9 +70,10 @@ pub(crate) fn run_query(
db: &RelationalDB,
tx: &mut MutTxId,
query: &QueryExpr,
query_debug_info: Option<&QueryDebugInfo>,
auth: AuthCtx,
) -> Result<Vec<MemTable>, DBError> {
execute_single_sql(db, tx, CrudExpr::Query(query.clone()), auth)
execute_single_sql(db, tx, CrudExpr::Query(query.clone()), query_debug_info, auth)
}

// TODO: It's semantically wrong to `SUBSCRIBE_TO_ALL_QUERY`
Expand Down Expand Up @@ -123,8 +125,13 @@ pub fn compile_read_only_query(
}
}

let info = QueryDebugInfo::from_source(input);

if !queries.is_empty() {
Ok(queries.into_iter().map(TryFrom::try_from).collect::<Result<_, _>>()?)
Ok(queries
.into_iter()
.map(|query| SupportedQuery::new(query, Some(info.clone())))
.collect::<Result<_, _>>()?)
} else {
Err(SubscriptionError::Empty.into())
}
Expand Down Expand Up @@ -331,7 +338,7 @@ mod tests {
data: &DatabaseTableUpdate,
) -> ResultTest<()> {
let q = to_mem_table(q.clone(), data);
let result = run_query(db, tx, &q, AuthCtx::for_testing())?;
let result = run_query(db, tx, &q, None, AuthCtx::for_testing())?;

assert_eq!(
Some(table.as_without_table_name()),
Expand Down Expand Up @@ -803,6 +810,7 @@ mod tests {
&db,
&mut tx,
&q,
None,
AuthCtx::new(Identity::__dummy(), Identity::from_byte_array([1u8; 32])),
) {
Ok(_) => {
Expand Down Expand Up @@ -925,7 +933,7 @@ mod tests {
let qset = compile_read_only_query(&db, &tx, &AuthCtx::for_testing(), sql_query)?;

for q in qset {
let result = run_query(&db, &mut tx, q.as_expr(), AuthCtx::for_testing())?;
let result = run_query(&db, &mut tx, q.as_expr(), None, AuthCtx::for_testing())?;
assert_eq!(result.len(), 1, "Join query did not return any rows");
}

Expand Down
Loading

1 comment on commit 419cfca

@github-actions
Copy link

@github-actions github-actions bot commented on 419cfca Nov 21, 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 💿 448.6±1.94ns 440.6±5.18ns - -
sqlite 🧠 440.1±3.08ns 427.4±2.93ns - -
stdb_module 💿 17.8±1.04µs 17.9±1.10µs - -
stdb_module 🧠 18.0±1.45µs 17.7±1.12µs - -
stdb_raw 💿 916.1±1.69ns 909.1±2.29ns - -
stdb_raw 🧠 872.2±2.86ns 870.3±5.92ns - -

Single-row insertions

db on disk schema index type load new latency old latency new throughput old throughput
sqlite 💿 location multi_index 0 15.1±2.27µs 14.4±0.04µs 64.5 Ktx/sec 68.0 Ktx/sec
sqlite 💿 location multi_index 1000 15.9±0.10µs 15.8±0.12µs 61.4 Ktx/sec 61.9 Ktx/sec
sqlite 💿 location non_unique 0 7.2±0.06µs 7.2±0.03µs 134.8 Ktx/sec 135.6 Ktx/sec
sqlite 💿 location non_unique 1000 7.1±0.05µs 7.1±0.06µs 137.9 Ktx/sec 137.2 Ktx/sec
sqlite 💿 location unique 0 7.3±0.05µs 7.3±1.06µs 134.0 Ktx/sec 134.5 Ktx/sec
sqlite 💿 location unique 1000 8.7±15.21µs 7.1±0.03µs 111.9 Ktx/sec 138.1 Ktx/sec
sqlite 💿 person multi_index 0 14.9±1.17µs 14.2±0.05µs 65.4 Ktx/sec 68.6 Ktx/sec
sqlite 💿 person multi_index 1000 16.1±0.14µs 16.1±0.12µs 60.6 Ktx/sec 60.8 Ktx/sec
sqlite 💿 person non_unique 0 7.4±0.63µs 7.3±0.96µs 131.3 Ktx/sec 133.3 Ktx/sec
sqlite 💿 person non_unique 1000 7.3±0.04µs 7.3±0.05µs 133.6 Ktx/sec 134.6 Ktx/sec
sqlite 💿 person unique 0 7.6±1.09µs 7.4±0.90µs 128.9 Ktx/sec 132.2 Ktx/sec
sqlite 💿 person unique 1000 7.3±0.04µs 7.2±0.05µs 133.1 Ktx/sec 134.8 Ktx/sec
sqlite 🧠 location multi_index 0 4.1±0.04µs 4.0±0.02µs 237.6 Ktx/sec 241.4 Ktx/sec
sqlite 🧠 location multi_index 1000 5.3±0.05µs 5.2±0.04µs 182.7 Ktx/sec 187.0 Ktx/sec
sqlite 🧠 location non_unique 0 1867.1±17.72ns 1843.8±5.13ns 523.0 Ktx/sec 529.7 Ktx/sec
sqlite 🧠 location non_unique 1000 1890.8±26.94ns 1886.6±12.85ns 516.5 Ktx/sec 517.6 Ktx/sec
sqlite 🧠 location unique 0 1849.9±18.16ns 1834.5±9.81ns 527.9 Ktx/sec 532.3 Ktx/sec
sqlite 🧠 location unique 1000 1947.8±10.46ns 1945.9±11.13ns 501.4 Ktx/sec 501.9 Ktx/sec
sqlite 🧠 person multi_index 0 3.8±0.02µs 3.6±0.01µs 256.2 Ktx/sec 269.1 Ktx/sec
sqlite 🧠 person multi_index 1000 5.6±0.12µs 5.4±0.02µs 173.7 Ktx/sec 180.2 Ktx/sec
sqlite 🧠 person non_unique 0 1962.1±5.26ns 1922.9±4.28ns 497.7 Ktx/sec 507.9 Ktx/sec
sqlite 🧠 person non_unique 1000 2.0±0.01µs 1981.7±8.62ns 478.2 Ktx/sec 492.8 Ktx/sec
sqlite 🧠 person unique 0 1935.4±7.30ns 1889.0±5.38ns 504.6 Ktx/sec 517.0 Ktx/sec
sqlite 🧠 person unique 1000 2.1±0.01µs 2.0±0.01µs 471.4 Ktx/sec 483.8 Ktx/sec
stdb_module 💿 location multi_index 0 48.6±4.51µs 52.1±4.58µs 20.1 Ktx/sec 18.7 Ktx/sec
stdb_module 💿 location multi_index 1000 163.8±4.47µs 276.1±7.23µs 6.0 Ktx/sec 3.5 Ktx/sec
stdb_module 💿 location non_unique 0 40.9±4.85µs 39.7±3.92µs 23.9 Ktx/sec 24.6 Ktx/sec
stdb_module 💿 location non_unique 1000 273.2±26.35µs 147.6±6.15µs 3.6 Ktx/sec 6.6 Ktx/sec
stdb_module 💿 location unique 0 45.0±5.44µs 45.1±5.28µs 21.7 Ktx/sec 21.6 Ktx/sec
stdb_module 💿 location unique 1000 250.5±67.07µs 164.2±75.32µs 3.9 Ktx/sec 5.9 Ktx/sec
stdb_module 💿 person multi_index 0 67.3±4.45µs 65.3±3.69µs 14.5 Ktx/sec 15.0 Ktx/sec
stdb_module 💿 person multi_index 1000 232.9±5.73µs 130.4±31.72µs 4.2 Ktx/sec 7.5 Ktx/sec
stdb_module 💿 person non_unique 0 50.2±3.96µs 49.9±4.83µs 19.4 Ktx/sec 19.6 Ktx/sec
stdb_module 💿 person non_unique 1000 193.1±2.16µs 138.6±80.33µs 5.1 Ktx/sec 7.0 Ktx/sec
stdb_module 💿 person unique 0 57.0±3.53µs 60.4±3.97µs 17.1 Ktx/sec 16.2 Ktx/sec
stdb_module 💿 person unique 1000 126.5±104.19µs 138.5±7.08µs 7.7 Ktx/sec 7.1 Ktx/sec
stdb_module 🧠 location multi_index 0 36.2±3.33µs 35.0±3.36µs 27.0 Ktx/sec 27.9 Ktx/sec
stdb_module 🧠 location multi_index 1000 118.1±21.69µs 186.4±10.39µs 8.3 Ktx/sec 5.2 Ktx/sec
stdb_module 🧠 location non_unique 0 31.3±2.37µs 29.9±2.90µs 31.2 Ktx/sec 32.7 Ktx/sec
stdb_module 🧠 location non_unique 1000 176.4±4.09µs 196.2±8.40µs 5.5 Ktx/sec 5.0 Ktx/sec
stdb_module 🧠 location unique 0 35.0±3.24µs 34.7±3.78µs 27.9 Ktx/sec 28.1 Ktx/sec
stdb_module 🧠 location unique 1000 121.7±11.98µs 186.7±7.13µs 8.0 Ktx/sec 5.2 Ktx/sec
stdb_module 🧠 person multi_index 0 46.2±4.12µs 45.5±4.82µs 21.1 Ktx/sec 21.5 Ktx/sec
stdb_module 🧠 person multi_index 1000 89.2±49.42µs 109.0±9.46µs 10.9 Ktx/sec 9.0 Ktx/sec
stdb_module 🧠 person non_unique 0 32.8±3.96µs 35.1±2.65µs 29.8 Ktx/sec 27.8 Ktx/sec
stdb_module 🧠 person non_unique 1000 188.7±9.92µs 253.6±23.67µs 5.2 Ktx/sec 3.9 Ktx/sec
stdb_module 🧠 person unique 0 40.0±2.72µs 41.8±4.88µs 24.4 Ktx/sec 23.4 Ktx/sec
stdb_module 🧠 person unique 1000 184.8±1.73µs 213.4±29.17µs 5.3 Ktx/sec 4.6 Ktx/sec
stdb_raw 💿 location multi_index 0 7.1±0.07µs 7.0±0.02µs 137.6 Ktx/sec 139.9 Ktx/sec
stdb_raw 💿 location multi_index 1000 9.9±0.19µs 9.6±0.16µs 98.7 Ktx/sec 101.5 Ktx/sec
stdb_raw 💿 location non_unique 0 4.7±0.02µs 4.5±0.01µs 208.4 Ktx/sec 216.3 Ktx/sec
stdb_raw 💿 location non_unique 1000 6.1±0.17µs 5.9±0.13µs 159.7 Ktx/sec 164.2 Ktx/sec
stdb_raw 💿 location unique 0 6.0±0.06µs 5.9±0.06µs 162.1 Ktx/sec 166.7 Ktx/sec
stdb_raw 💿 location unique 1000 22.3±139.34µs 8.2±0.18µs 43.7 Ktx/sec 119.4 Ktx/sec
stdb_raw 💿 person multi_index 0 11.3±0.02µs 11.2±0.36µs 86.4 Ktx/sec 87.0 Ktx/sec
stdb_raw 💿 person multi_index 1000 65.5±508.70µs 14.5±0.16µs 14.9 Ktx/sec 67.5 Ktx/sec
stdb_raw 💿 person non_unique 0 5.8±0.08µs 5.6±0.01µs 169.2 Ktx/sec 173.9 Ktx/sec
stdb_raw 💿 person non_unique 1000 18.9±114.58µs 19.2±119.29µs 51.6 Ktx/sec 50.8 Ktx/sec
stdb_raw 💿 person unique 0 8.2±0.03µs 8.0±0.02µs 118.5 Ktx/sec 122.0 Ktx/sec
stdb_raw 💿 person unique 1000 38.3±274.72µs 32.0±213.71µs 25.5 Ktx/sec 30.5 Ktx/sec
stdb_raw 🧠 location multi_index 0 4.4±0.01µs 4.4±0.01µs 219.6 Ktx/sec 223.5 Ktx/sec
stdb_raw 🧠 location multi_index 1000 6.0±0.05µs 6.0±0.04µs 164.1 Ktx/sec 162.6 Ktx/sec
stdb_raw 🧠 location non_unique 0 2.2±0.01µs 2.1±0.00µs 447.8 Ktx/sec 463.7 Ktx/sec
stdb_raw 🧠 location non_unique 1000 2.6±0.01µs 2.7±0.01µs 369.1 Ktx/sec 367.0 Ktx/sec
stdb_raw 🧠 location unique 0 3.4±0.01µs 3.3±0.01µs 283.2 Ktx/sec 293.5 Ktx/sec
stdb_raw 🧠 location unique 1000 4.6±0.03µs 4.6±0.03µs 213.3 Ktx/sec 213.4 Ktx/sec
stdb_raw 🧠 person multi_index 0 8.2±0.01µs 8.1±0.01µs 118.7 Ktx/sec 121.1 Ktx/sec
stdb_raw 🧠 person multi_index 1000 10.3±0.08µs 10.2±0.08µs 94.4 Ktx/sec 95.5 Ktx/sec
stdb_raw 🧠 person non_unique 0 2.7±0.01µs 2.7±0.01µs 356.3 Ktx/sec 365.1 Ktx/sec
stdb_raw 🧠 person non_unique 1000 3.5±0.04µs 3.4±0.02µs 279.2 Ktx/sec 286.0 Ktx/sec
stdb_raw 🧠 person unique 0 5.1±0.02µs 5.0±0.01µs 191.0 Ktx/sec 196.5 Ktx/sec
stdb_raw 🧠 person unique 1000 6.5±0.04µs 6.5±0.03µs 149.8 Ktx/sec 150.7 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 131.7±4.06µs 131.2±4.58µs 7.4 Ktx/sec 7.4 Ktx/sec
sqlite 💿 location multi_index 1000 100 201.7±1.55µs 202.4±1.07µs 4.8 Ktx/sec 4.8 Ktx/sec
sqlite 💿 location non_unique 0 100 50.3±1.48µs 49.7±1.44µs 19.4 Ktx/sec 19.6 Ktx/sec
sqlite 💿 location non_unique 1000 100 52.4±0.49µs 53.2±0.23µs 18.6 Ktx/sec 18.4 Ktx/sec
sqlite 💿 location unique 0 100 51.0±0.40µs 52.2±0.80µs 19.2 Ktx/sec 18.7 Ktx/sec
sqlite 💿 location unique 1000 100 56.7±0.33µs 56.6±0.28µs 17.2 Ktx/sec 17.2 Ktx/sec
sqlite 💿 person multi_index 0 100 119.3±12.25µs 118.1±6.52µs 8.2 Ktx/sec 8.3 Ktx/sec
sqlite 💿 person multi_index 1000 100 229.2±0.69µs 230.0±0.44µs 4.3 Ktx/sec 4.2 Ktx/sec
sqlite 💿 person non_unique 0 100 48.2±0.32µs 49.0±0.28µs 20.3 Ktx/sec 19.9 Ktx/sec
sqlite 💿 person non_unique 1000 100 60.2±0.34µs 61.4±0.28µs 16.2 Ktx/sec 15.9 Ktx/sec
sqlite 💿 person unique 0 100 49.3±1.73µs 50.2±0.52µs 19.8 Ktx/sec 19.5 Ktx/sec
sqlite 💿 person unique 1000 100 55.7±0.28µs 55.8±0.23µs 17.5 Ktx/sec 17.5 Ktx/sec
sqlite 🧠 location multi_index 0 100 118.7±0.30µs 118.6±0.55µs 8.2 Ktx/sec 8.2 Ktx/sec
sqlite 🧠 location multi_index 1000 100 171.1±0.44µs 170.0±0.35µs 5.7 Ktx/sec 5.7 Ktx/sec
sqlite 🧠 location non_unique 0 100 43.3±0.38µs 43.3±0.35µs 22.6 Ktx/sec 22.6 Ktx/sec
sqlite 🧠 location non_unique 1000 100 44.2±0.43µs 45.8±0.21µs 22.1 Ktx/sec 21.3 Ktx/sec
sqlite 🧠 location unique 0 100 45.0±0.33µs 45.2±0.65µs 21.7 Ktx/sec 21.6 Ktx/sec
sqlite 🧠 location unique 1000 100 48.5±0.36µs 48.8±0.27µs 20.1 Ktx/sec 20.0 Ktx/sec
sqlite 🧠 person multi_index 0 100 106.9±1.05µs 107.3±0.37µs 9.1 Ktx/sec 9.1 Ktx/sec
sqlite 🧠 person multi_index 1000 100 190.5±0.67µs 190.4±0.29µs 5.1 Ktx/sec 5.1 Ktx/sec
sqlite 🧠 person non_unique 0 100 41.8±0.33µs 43.4±0.51µs 23.3 Ktx/sec 22.5 Ktx/sec
sqlite 🧠 person non_unique 1000 100 45.7±0.23µs 47.4±0.55µs 21.4 Ktx/sec 20.6 Ktx/sec
sqlite 🧠 person unique 0 100 42.5±0.29µs 44.7±0.19µs 23.0 Ktx/sec 21.8 Ktx/sec
sqlite 🧠 person unique 1000 100 47.6±0.34µs 48.3±0.26µs 20.5 Ktx/sec 20.2 Ktx/sec
stdb_module 💿 location multi_index 0 100 674.4±139.94µs 628.2±102.62µs 1482 tx/sec 1591 tx/sec
stdb_module 💿 location multi_index 1000 100 1128.2±9.09µs 759.2±85.89µs 886 tx/sec 1317 tx/sec
stdb_module 💿 location non_unique 0 100 469.8±193.06µs 425.7±41.81µs 2.1 Ktx/sec 2.3 Ktx/sec
stdb_module 💿 location non_unique 1000 100 606.0±78.76µs 481.6±28.62µs 1650 tx/sec 2.0 Ktx/sec
stdb_module 💿 location unique 0 100 689.1±471.53µs 600.6±93.89µs 1451 tx/sec 1664 tx/sec
stdb_module 💿 location unique 1000 100 574.1±51.62µs 837.1±85.40µs 1741 tx/sec 1194 tx/sec
stdb_module 💿 person multi_index 0 100 1117.2±191.90µs 1074.1±81.75µs 895 tx/sec 930 tx/sec
stdb_module 💿 person multi_index 1000 100 1289.6±10.47µs 1340.3±17.16µs 775 tx/sec 746 tx/sec
stdb_module 💿 person non_unique 0 100 703.3±89.07µs 694.1±29.94µs 1421 tx/sec 1440 tx/sec
stdb_module 💿 person non_unique 1000 100 768.1±3.80µs 660.1±44.23µs 1301 tx/sec 1514 tx/sec
stdb_module 💿 person unique 0 100 821.4±159.99µs 728.8±96.84µs 1217 tx/sec 1372 tx/sec
stdb_module 💿 person unique 1000 100 829.2±103.29µs 756.9±40.52µs 1206 tx/sec 1321 tx/sec
stdb_module 🧠 location multi_index 0 100 645.3±128.06µs 644.3±124.07µs 1549 tx/sec 1552 tx/sec
stdb_module 🧠 location multi_index 1000 100 800.1±11.14µs 630.1±3.00µs 1249 tx/sec 1587 tx/sec
stdb_module 🧠 location non_unique 0 100 378.6±13.99µs 348.8±53.20µs 2.6 Ktx/sec 2.8 Ktx/sec
stdb_module 🧠 location non_unique 1000 100 392.6±13.85µs 382.4±23.69µs 2.5 Ktx/sec 2.6 Ktx/sec
stdb_module 🧠 location unique 0 100 413.5±41.87µs 587.6±1.47µs 2.4 Ktx/sec 1701 tx/sec
stdb_module 🧠 location unique 1000 100 490.1±8.90µs 635.4±86.79µs 2040 tx/sec 1573 tx/sec
stdb_module 🧠 person multi_index 0 100 924.5±12.80µs 869.4±1.69µs 1081 tx/sec 1150 tx/sec
stdb_module 🧠 person multi_index 1000 100 932.9±36.55µs 1063.6±24.20µs 1071 tx/sec 940 tx/sec
stdb_module 🧠 person non_unique 0 100 523.0±7.68µs 414.5±24.01µs 1912 tx/sec 2.4 Ktx/sec
stdb_module 🧠 person non_unique 1000 100 487.2±84.61µs 710.6±11.26µs 2.0 Ktx/sec 1407 tx/sec
stdb_module 🧠 person unique 0 100 600.3±81.93µs 594.0±6.75µs 1665 tx/sec 1683 tx/sec
stdb_module 🧠 person unique 1000 100 663.5±9.71µs 568.7±13.93µs 1507 tx/sec 1758 tx/sec
stdb_raw 💿 location multi_index 0 100 344.8±27.01µs 346.6±0.36µs 2.8 Ktx/sec 2.8 Ktx/sec
stdb_raw 💿 location multi_index 1000 100 393.8±271.50µs 392.4±209.01µs 2.5 Ktx/sec 2.5 Ktx/sec
stdb_raw 💿 location non_unique 0 100 119.1±12.93µs 119.7±0.35µs 8.2 Ktx/sec 8.2 Ktx/sec
stdb_raw 💿 location non_unique 1000 100 130.5±108.69µs 122.2±1.70µs 7.5 Ktx/sec 8.0 Ktx/sec
stdb_raw 💿 location unique 0 100 241.3±0.31µs 245.7±4.27µs 4.0 Ktx/sec 4.0 Ktx/sec
stdb_raw 💿 location unique 1000 100 259.8±1.45µs 281.0±191.23µs 3.8 Ktx/sec 3.5 Ktx/sec
stdb_raw 💿 person multi_index 0 100 709.8±1.39µs 710.0±2.23µs 1408 tx/sec 1408 tx/sec
stdb_raw 💿 person multi_index 1000 100 774.9±357.53µs 788.2±482.30µs 1290 tx/sec 1268 tx/sec
stdb_raw 💿 person non_unique 0 100 217.9±0.94µs 219.0±0.23µs 4.5 Ktx/sec 4.5 Ktx/sec
stdb_raw 💿 person non_unique 1000 100 220.3±0.46µs 222.2±3.61µs 4.4 Ktx/sec 4.4 Ktx/sec
stdb_raw 💿 person unique 0 100 428.5±0.35µs 430.6±12.03µs 2.3 Ktx/sec 2.3 Ktx/sec
stdb_raw 💿 person unique 1000 100 474.2±273.66µs 446.4±0.97µs 2.1 Ktx/sec 2.2 Ktx/sec
stdb_raw 🧠 location multi_index 0 100 295.4±0.72µs 303.3±2.27µs 3.3 Ktx/sec 3.2 Ktx/sec
stdb_raw 🧠 location multi_index 1000 100 320.7±0.53µs 328.1±0.60µs 3.0 Ktx/sec 3.0 Ktx/sec
stdb_raw 🧠 location non_unique 0 100 75.0±0.75µs 76.8±0.36µs 13.0 Ktx/sec 12.7 Ktx/sec
stdb_raw 🧠 location non_unique 1000 100 76.2±0.13µs 78.0±0.26µs 12.8 Ktx/sec 12.5 Ktx/sec
stdb_raw 🧠 location unique 0 100 198.4±0.28µs 202.0±0.30µs 4.9 Ktx/sec 4.8 Ktx/sec
stdb_raw 🧠 location unique 1000 100 216.4±0.62µs 220.2±0.74µs 4.5 Ktx/sec 4.4 Ktx/sec
stdb_raw 🧠 person multi_index 0 100 617.8±0.83µs 616.8±1.02µs 1618 tx/sec 1621 tx/sec
stdb_raw 🧠 person multi_index 1000 100 648.5±1.01µs 647.7±1.27µs 1541 tx/sec 1543 tx/sec
stdb_raw 🧠 person non_unique 0 100 127.0±0.37µs 128.3±0.24µs 7.7 Ktx/sec 7.6 Ktx/sec
stdb_raw 🧠 person non_unique 1000 100 129.3±0.23µs 130.3±0.27µs 7.6 Ktx/sec 7.5 Ktx/sec
stdb_raw 🧠 person unique 0 100 337.7±0.49µs 335.7±0.86µs 2.9 Ktx/sec 2.9 Ktx/sec
stdb_raw 🧠 person unique 1000 100 356.4±0.61µs 354.9±0.39µs 2.7 Ktx/sec 2.8 Ktx/sec

Full table iterate

db on disk schema index type new latency old latency new throughput old throughput
sqlite 💿 location unique 8.7±0.06µs 9.0±0.09µs 111.9 Ktx/sec 108.5 Ktx/sec
sqlite 💿 person unique 9.2±0.11µs 9.6±0.13µs 105.6 Ktx/sec 102.1 Ktx/sec
sqlite 🧠 location unique 7.5±0.12µs 8.0±0.07µs 129.8 Ktx/sec 121.3 Ktx/sec
sqlite 🧠 person unique 7.9±0.08µs 8.5±0.07µs 123.4 Ktx/sec 115.2 Ktx/sec
stdb_module 💿 location unique 48.7±5.13µs 47.9±2.80µs 20.1 Ktx/sec 20.4 Ktx/sec
stdb_module 💿 person unique 56.4±8.62µs 60.6±8.68µs 17.3 Ktx/sec 16.1 Ktx/sec
stdb_module 🧠 location unique 48.4±5.08µs 49.4±4.70µs 20.2 Ktx/sec 19.8 Ktx/sec
stdb_module 🧠 person unique 61.6±6.20µs 56.0±9.64µs 15.9 Ktx/sec 17.4 Ktx/sec
stdb_raw 💿 location unique 9.2±0.02µs 9.8±0.09µs 106.0 Ktx/sec 99.5 Ktx/sec
stdb_raw 💿 person unique 9.2±0.10µs 9.8±0.02µs 105.9 Ktx/sec 99.4 Ktx/sec
stdb_raw 🧠 location unique 9.2±0.10µs 9.8±0.04µs 106.5 Ktx/sec 100.0 Ktx/sec
stdb_raw 🧠 person unique 9.2±0.02µs 9.8±0.03µs 106.5 Ktx/sec 100.0 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.3±0.02µs 414.8 Ktx/sec 416.4 Ktx/sec
sqlite 🧠 u32 1000 1117.4±9.99ns 1120.8±6.75ns 874.0 Ktx/sec 871.3 Ktx/sec
stdb_module 💿 u32 1000 25.3±2.69µs 26.1±3.32µs 38.6 Ktx/sec 37.5 Ktx/sec
stdb_module 🧠 u32 1000 23.9±1.47µs 25.1±2.46µs 40.9 Ktx/sec 38.9 Ktx/sec
stdb_raw 💿 u32 1000 2.2±0.00µs 2.1±0.01µs 448.2 Ktx/sec 454.9 Ktx/sec
stdb_raw 🧠 u32 1000 2.1±0.02µs 2.1±0.01µs 464.5 Ktx/sec 468.9 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.03µs 5.6±0.02µs 174.6 Ktx/sec 174.0 Ktx/sec
sqlite 💿 string non_indexed 1000 10 48.4±0.85µs 53.3±0.94µs 20.2 Ktx/sec 18.3 Ktx/sec
sqlite 💿 u64 indexed 1000 10 5.4±0.02µs 5.4±0.01µs 181.4 Ktx/sec 182.1 Ktx/sec
sqlite 💿 u64 non_indexed 1000 10 32.8±0.05µs 33.1±0.19µs 29.8 Ktx/sec 29.5 Ktx/sec
sqlite 🧠 string indexed 1000 10 4.1±0.02µs 4.2±0.04µs 236.2 Ktx/sec 231.9 Ktx/sec
sqlite 🧠 string non_indexed 1000 10 46.6±0.21µs 52.6±1.22µs 21.0 Ktx/sec 18.6 Ktx/sec
sqlite 🧠 u64 indexed 1000 10 4.0±0.01µs 4.0±0.02µs 246.1 Ktx/sec 244.6 Ktx/sec
sqlite 🧠 u64 non_indexed 1000 10 31.6±0.05µs 32.0±0.52µs 30.9 Ktx/sec 30.5 Ktx/sec
stdb_module 💿 string indexed 1000 10 33.7±3.28µs 35.0±1.83µs 29.0 Ktx/sec 27.9 Ktx/sec
stdb_module 💿 string non_indexed 1000 10 173.9±6.80µs 169.8±1.66µs 5.6 Ktx/sec 5.8 Ktx/sec
stdb_module 💿 u64 indexed 1000 10 32.4±2.48µs 33.7±1.49µs 30.1 Ktx/sec 29.0 Ktx/sec
stdb_module 💿 u64 non_indexed 1000 10 142.9±13.80µs 145.5±2.13µs 6.8 Ktx/sec 6.7 Ktx/sec
stdb_module 🧠 string indexed 1000 10 34.8±2.15µs 36.2±2.32µs 28.1 Ktx/sec 27.0 Ktx/sec
stdb_module 🧠 string non_indexed 1000 10 162.6±0.98µs 167.9±1.25µs 6.0 Ktx/sec 5.8 Ktx/sec
stdb_module 🧠 u64 indexed 1000 10 32.1±2.35µs 33.1±2.53µs 30.5 Ktx/sec 29.5 Ktx/sec
stdb_module 🧠 u64 non_indexed 1000 10 135.0±0.44µs 140.3±0.95µs 7.2 Ktx/sec 7.0 Ktx/sec
stdb_raw 💿 string indexed 1000 10 4.7±0.01µs 4.6±0.01µs 207.2 Ktx/sec 210.3 Ktx/sec
stdb_raw 💿 string non_indexed 1000 10 141.7±0.29µs 149.4±0.42µs 6.9 Ktx/sec 6.5 Ktx/sec
stdb_raw 💿 u64 indexed 1000 10 4.6±0.01µs 4.5±0.01µs 213.1 Ktx/sec 215.5 Ktx/sec
stdb_raw 💿 u64 non_indexed 1000 10 117.3±0.33µs 120.0±0.32µs 8.3 Ktx/sec 8.1 Ktx/sec
stdb_raw 🧠 string indexed 1000 10 4.6±0.01µs 4.6±0.01µs 210.8 Ktx/sec 212.9 Ktx/sec
stdb_raw 🧠 string non_indexed 1000 10 138.0±0.25µs 146.5±0.25µs 7.1 Ktx/sec 6.7 Ktx/sec
stdb_raw 🧠 u64 indexed 1000 10 4.5±0.01µs 4.5±0.01µs 216.4 Ktx/sec 218.7 Ktx/sec
stdb_raw 🧠 u64 non_indexed 1000 10 116.2±0.15µs 119.3±0.14µs 8.4 Ktx/sec 8.2 Ktx/sec

Serialize

schema format count new latency old latency new throughput old throughput
location bsatn 100 1852.6±34.18ns 1856.3±33.03ns 51.5 Mtx/sec 51.4 Mtx/sec
location json 100 3.4±0.14µs 3.4±0.12µs 28.2 Mtx/sec 28.0 Mtx/sec
location product_value 100 605.8±0.45ns 606.5±1.12ns 157.4 Mtx/sec 157.2 Mtx/sec
person bsatn 100 2.6±0.01µs 2.6±0.03µs 36.4 Mtx/sec 36.5 Mtx/sec
person json 100 5.2±0.02µs 4.9±0.03µs 18.3 Mtx/sec 19.3 Mtx/sec
person product_value 100 1008.9±0.97ns 1006.5±0.72ns 94.5 Mtx/sec 94.8 Mtx/sec

Module: invoke with large arguments

arg size new latency old latency new throughput old throughput
64KiB 70.5±4.46µs 64.0±10.17µs - -

Module: print bulk

line count new latency old latency new throughput old throughput
1 22.8±1.51µs 23.1±1.81µs - -
100 189.2±4.71µs 188.9±1.32µs - -
1000 1674.5±38.49µs 1703.3±66.36µs - -

Remaining benchmarks

name new latency old latency new throughput old throughput

Please sign in to comment.