Skip to content

Commit

Permalink
Re-add execute_sql_mut_tx (#1313)
Browse files Browse the repository at this point in the history
  • Loading branch information
coolreader18 authored Jun 3, 2024
1 parent 74bcecd commit a854945
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 39 deletions.
20 changes: 5 additions & 15 deletions crates/core/src/host/wasm_common/module_host_actor.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use anyhow::{anyhow, Context};
use anyhow::Context;
use bytes::Bytes;
use std::sync::Arc;
use std::time::Duration;

use spacetimedb_lib::buffer::DecodeError;
use spacetimedb_lib::identity::AuthCtx;
use spacetimedb_lib::{bsatn, Address, ModuleDef, ModuleValidationError, TableDesc};
use spacetimedb_vm::expr::CrudExpr;

use super::instrumentation::CallTimes;
use crate::database_instance_context::DatabaseInstanceContext;
Expand Down Expand Up @@ -278,20 +277,11 @@ impl<T: WasmModule> Module for WasmModuleHostActor<T> {
log::debug!("One-off query: {query}");
// Don't need the `slow query` logger on compilation
let ctx = &ExecutionContext::sql(db.address(), db.read_config().slow_query);
let compiled: Vec<_> = db.with_read_only(ctx, |tx| {
db.with_read_only(ctx, |tx| {
let ast = sql::compiler::compile_sql(db, tx, &query)?;
ast.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, &query, compiled, auth)
sql::execute::execute_sql_tx(db, tx, &query, ast, auth)
.and_then(|res| Ok(res.context("One-off queries are not allowed to modify the database")?))
})
}

fn clear_table(&self, table_name: &str) -> Result<(), anyhow::Error> {
Expand Down
69 changes: 54 additions & 15 deletions crates/core/src/sql/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::error::DBError;
use crate::execution_context::ExecutionContext;
use crate::util::slow::SlowQueryLogger;
use crate::vm::{DbProgram, TxMode};
use itertools::Either;
use spacetimedb_lib::identity::AuthCtx;
use spacetimedb_lib::relation::FieldName;
use spacetimedb_lib::{ProductType, ProductValue};
Expand Down Expand Up @@ -40,40 +41,78 @@ pub fn ctx_sql(db: &RelationalDB) -> ExecutionContext {
ExecutionContext::sql(db.address(), db.read_config().slow_query)
}

fn execute(p: &mut DbProgram<'_, '_>, ast: Vec<CrudExpr>) -> Result<Vec<MemTable>, DBError> {
let mut result = Vec::with_capacity(ast.len());
let query = Expr::Block(ast.into_iter().map(|x| Expr::Crud(Box::new(x))).collect());
// SQL queries can never reference `MemTable`s, so pass an empty `SourceSet`.
collect_result(&mut result, run_ast(p, query, [].into()).into())?;
Ok(result)
}

/// Run the compiled `SQL` expression inside the `vm` created by [DbProgram]
///
/// Evaluates `ast` and accordingly triggers mutable or read tx to execute
///
/// Also, in case the execution takes more than x, log it as `slow query`
pub fn execute_sql(db: &RelationalDB, sql: &str, ast: Vec<CrudExpr>, auth: AuthCtx) -> Result<Vec<MemTable>, DBError> {
fn execute(p: &mut DbProgram<'_, '_>, ast: Vec<CrudExpr>) -> Result<Vec<MemTable>, DBError> {
let mut result = Vec::with_capacity(ast.len());
let query = Expr::Block(ast.into_iter().map(|x| Expr::Crud(Box::new(x))).collect());
// SQL queries can never reference `MemTable`s, so pass an empty `SourceSet`.
collect_result(&mut result, run_ast(p, query, [].into()).into())?;
Ok(result)
}

let ctx = ctx_sql(db);
let slow_logger = SlowQueryLogger::query(&ctx, sql);
let result = if CrudExpr::is_reads(&ast) {
let _slow_logger = SlowQueryLogger::query(&ctx, sql).log_guard();
if CrudExpr::is_reads(&ast) {
db.with_read_only(&ctx, |tx| {
execute(&mut DbProgram::new(&ctx, db, &mut TxMode::Tx(tx), auth), ast)
})
} else {
db.with_auto_commit(&ctx, |mut_tx| {
execute(&mut DbProgram::new(&ctx, db, &mut mut_tx.into(), auth), ast)
})
}?;
slow_logger.log();
}
}

Ok(result)
/// Like [`execute_sql`], but for providing your own `tx`.
///
/// Returns None if you pass a mutable query with an immutable tx.
pub fn execute_sql_tx<'a>(
db: &RelationalDB,
tx: impl Into<TxMode<'a>>,
sql: &str,
ast: Vec<CrudExpr>,
auth: AuthCtx,
) -> Result<Option<Vec<MemTable>>, DBError> {
let mut tx = tx.into();

if matches!(tx, TxMode::Tx(_)) && !CrudExpr::is_reads(&ast) {
return Ok(None);
}

let ctx = ctx_sql(db);
let _slow_logger = SlowQueryLogger::query(&ctx, sql).log_guard();
execute(&mut DbProgram::new(&ctx, db, &mut tx, auth), ast).map(Some)
}

/// Run the `SQL` string using the `auth` credentials
pub fn run(db: &RelationalDB, sql_text: &str, auth: AuthCtx) -> Result<Vec<MemTable>, DBError> {
let ast = db.with_read_only(&ctx_sql(db), |tx| compile_sql(db, tx, sql_text))?;
execute_sql(db, sql_text, ast, auth)
let ctx = ctx_sql(db);
let _slow_logger = SlowQueryLogger::query(&ctx, sql_text).log_guard();
let result = db.with_read_only(&ctx, |tx| {
let ast = compile_sql(db, tx, sql_text)?;
if CrudExpr::is_reads(&ast) {
let result = execute(&mut DbProgram::new(&ctx, db, &mut TxMode::Tx(tx), auth), ast)?;
Ok::<_, DBError>(Either::Left(result))
} else {
// hehe. right. write.
Ok(Either::Right(ast))
}
})?;
match result {
Either::Left(result) => Ok(result),
// TODO: this should perhaps be an upgradable_read upgrade? or we should try
// and figure out if we can detect the mutablility of the query before we take
// the tx? once we have migrations we probably don't want to have stale
// sql queries after a database schema have been updated.
Either::Right(ast) => db.with_auto_commit(&ctx, |tx| {
execute(&mut DbProgram::new(&ctx, db, &mut tx.into(), auth), ast)
}),
}
}

/// Translates a `FieldName` to the field's name.
Expand Down
6 changes: 2 additions & 4 deletions crates/core/src/subscription/execution_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,9 @@ impl ExecutionUnit {
convert: impl FnMut(RelValue<'_>) -> T,
) -> Result<Vec<T>, DBError> {
let tx: TxMode = tx.into();
let slow_query = SlowQueryLogger::subscription(ctx, sql);
let _slow_query = SlowQueryLogger::subscription(ctx, sql).log_guard();
let query = build_query(ctx, db, &tx, eval_plan, &mut NoInMemUsed)?;
let ops = query.collect_vec(convert)?;
slow_query.log();
Ok(ops)
}

Expand All @@ -277,12 +276,11 @@ impl ExecutionUnit {
sql: &'a str,
tables: impl 'a + Clone + Iterator<Item = &'a DatabaseTableUpdate>,
) -> Result<Option<DatabaseTableUpdateRelValue<'a>>, DBError> {
let slow_query = SlowQueryLogger::incremental_updates(ctx, sql);
let _slow_query = SlowQueryLogger::incremental_updates(ctx, sql).log_guard();
let updates = match &self.eval_incr_plan {
EvalIncrPlan::Select(plan) => Self::eval_incr_query_expr(ctx, db, tx, tables, plan, self.return_table())?,
EvalIncrPlan::Semijoin(plan) => plan.eval(ctx, db, tx, tables)?,
};
slow_query.log();

Ok(updates.has_updates().then(|| DatabaseTableUpdateRelValue {
table_id: self.return_table(),
Expand Down
15 changes: 10 additions & 5 deletions crates/core/src/util/slow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,21 @@ impl<'a> SlowQueryLogger<'a> {
Self::new(sql, &ctx.slow_query_config.incremental_updates, ctx.workload())
}

pub fn log_guard(self) -> impl Drop + 'a {
scopeguard::guard(self, |logger| {
logger.log();
})
}

/// Log as `tracing::warn!` the query if it exceeds the threshold.
pub fn log(&self) -> Option<Duration> {
if let Some((start, threshold)) = self.start.zip(self.threshold.as_ref()) {
if let Some((start, threshold)) = self.start.zip(*self.threshold) {
let elapsed = start.elapsed();
if &elapsed > threshold {
let workload = self.workload.as_ref();
tracing::warn!(?workload, ?threshold, ?elapsed, ?self.sql, "SLOW QUERY");
if elapsed > threshold {
tracing::warn!(workload = %self.workload, ?threshold, ?elapsed, sql = ?self.sql, "SLOW QUERY");
return Some(elapsed);
}
};
}
None
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ impl<'a> From<&'a Tx> for TxMode<'a> {
}
}

impl<'a> From<&'a mut Tx> for TxMode<'a> {
fn from(tx: &'a mut Tx) -> Self {
TxMode::Tx(tx)
}
}

fn bound_is_satisfiable(lower: &Bound<AlgebraicValue>, upper: &Bound<AlgebraicValue>) -> bool {
match (lower, upper) {
(Bound::Excluded(lower), Bound::Excluded(upper)) if lower >= upper => false,
Expand Down

3 comments on commit a854945

@github-actions
Copy link

@github-actions github-actions bot commented on a854945 Jun 3, 2024

Choose a reason for hiding this comment

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

Bot test failed. Please check the workflow run for details.

@github-actions
Copy link

@github-actions github-actions bot commented on a854945 Jun 3, 2024

Choose a reason for hiding this comment

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

Criterion benchmark results

Criterion benchmark report

YOU SHOULD PROBABLY IGNORE THESE RESULTS.

Criterion is a wall time based benchmarking system that is extremely noisy when run on CI. We collect these results for longitudinal analysis, but they are not reliable for comparing individual PRs.

Go look at the callgrind report instead.

empty

db on disk new latency old latency new throughput old throughput
sqlite 💿 424.1±2.05ns 419.4±2.28ns - -
sqlite 🧠 415.3±1.50ns 409.7±1.96ns - -
stdb_raw 💿 717.6±3.92ns 715.7±1.07ns - -
stdb_raw 🧠 687.1±0.78ns 684.4±3.48ns - -

insert_1

db on disk schema indices preload new latency old latency new throughput old throughput

insert_bulk

db on disk schema indices preload count new latency old latency new throughput old throughput
sqlite 💿 u32_u64_str btree_each_column 2048 256 512.2±0.48µs 521.6±35.70µs 1952 tx/sec 1917 tx/sec
sqlite 💿 u32_u64_str unique_0 2048 256 137.1±0.79µs 136.6±0.54µs 7.1 Ktx/sec 7.1 Ktx/sec
sqlite 💿 u32_u64_u64 btree_each_column 2048 256 413.5±0.54µs 415.4±0.31µs 2.4 Ktx/sec 2.4 Ktx/sec
sqlite 💿 u32_u64_u64 unique_0 2048 256 124.6±1.35µs 123.8±0.54µs 7.8 Ktx/sec 7.9 Ktx/sec
sqlite 🧠 u32_u64_str btree_each_column 2048 256 444.0±1.16µs 447.5±0.98µs 2.2 Ktx/sec 2.2 Ktx/sec
sqlite 🧠 u32_u64_str unique_0 2048 256 123.2±0.36µs 122.4±0.59µs 7.9 Ktx/sec 8.0 Ktx/sec
sqlite 🧠 u32_u64_u64 btree_each_column 2048 256 364.0±0.55µs 364.8±0.40µs 2.7 Ktx/sec 2.7 Ktx/sec
sqlite 🧠 u32_u64_u64 unique_0 2048 256 104.5±0.71µs 104.9±0.28µs 9.3 Ktx/sec 9.3 Ktx/sec
stdb_raw 💿 u32_u64_str btree_each_column 2048 256 485.2±17.59µs 581.1±37.96µs 2.0 Ktx/sec 1721 tx/sec
stdb_raw 💿 u32_u64_str unique_0 2048 256 471.7±37.67µs 470.4±22.35µs 2.1 Ktx/sec 2.1 Ktx/sec
stdb_raw 💿 u32_u64_u64 btree_each_column 2048 256 364.1±15.85µs 333.9±5.57µs 2.7 Ktx/sec 2.9 Ktx/sec
stdb_raw 💿 u32_u64_u64 unique_0 2048 256 347.2±10.73µs 305.8±9.73µs 2.8 Ktx/sec 3.2 Ktx/sec
stdb_raw 🧠 u32_u64_str btree_each_column 2048 256 313.7±0.33µs 319.0±0.20µs 3.1 Ktx/sec 3.1 Ktx/sec
stdb_raw 🧠 u32_u64_str unique_0 2048 256 243.0±0.35µs 241.5±0.13µs 4.0 Ktx/sec 4.0 Ktx/sec
stdb_raw 🧠 u32_u64_u64 btree_each_column 2048 256 237.5±0.07µs 241.1±0.26µs 4.1 Ktx/sec 4.1 Ktx/sec
stdb_raw 🧠 u32_u64_u64 unique_0 2048 256 214.2±0.24µs 212.6±0.16µs 4.6 Ktx/sec 4.6 Ktx/sec

iterate

db on disk schema indices new latency old latency new throughput old throughput
sqlite 💿 u32_u64_str unique_0 20.3±0.29µs 21.3±0.23µs 48.1 Ktx/sec 45.8 Ktx/sec
sqlite 💿 u32_u64_u64 unique_0 19.1±0.28µs 20.1±0.12µs 51.1 Ktx/sec 48.7 Ktx/sec
sqlite 🧠 u32_u64_str unique_0 18.9±0.19µs 19.9±0.26µs 51.6 Ktx/sec 49.0 Ktx/sec
sqlite 🧠 u32_u64_u64 unique_0 18.0±0.31µs 18.1±0.21µs 54.2 Ktx/sec 53.9 Ktx/sec
stdb_raw 💿 u32_u64_str unique_0 3.8±0.00µs 3.8±0.00µs 256.0 Ktx/sec 255.6 Ktx/sec
stdb_raw 💿 u32_u64_u64 unique_0 3.7±0.00µs 3.7±0.00µs 263.3 Ktx/sec 263.3 Ktx/sec
stdb_raw 🧠 u32_u64_str unique_0 3.8±0.00µs 3.8±0.00µs 258.8 Ktx/sec 258.8 Ktx/sec
stdb_raw 🧠 u32_u64_u64 unique_0 3.7±0.00µs 3.7±0.00µs 265.5 Ktx/sec 265.5 Ktx/sec

find_unique

db on disk key type preload new latency old latency new throughput old throughput

filter

db on disk key type index strategy load count new latency old latency new throughput old throughput
sqlite 💿 string index 2048 256 67.5±0.70µs 67.5±0.18µs 14.5 Ktx/sec 14.5 Ktx/sec
sqlite 💿 u64 index 2048 256 65.6±0.07µs 64.3±0.22µs 14.9 Ktx/sec 15.2 Ktx/sec
sqlite 🧠 string index 2048 256 64.9±0.25µs 65.1±0.18µs 15.0 Ktx/sec 15.0 Ktx/sec
sqlite 🧠 u64 index 2048 256 61.1±0.13µs 59.8±0.45µs 16.0 Ktx/sec 16.3 Ktx/sec
stdb_raw 💿 string index 2048 256 5.1±0.00µs 5.1±0.00µs 192.4 Ktx/sec 192.4 Ktx/sec
stdb_raw 💿 u64 index 2048 256 5.0±0.00µs 5.0±0.00µs 195.2 Ktx/sec 195.2 Ktx/sec
stdb_raw 🧠 string index 2048 256 5.0±0.00µs 5.0±0.00µs 193.7 Ktx/sec 193.8 Ktx/sec
stdb_raw 🧠 u64 index 2048 256 5.0±0.00µs 5.0±0.00µs 196.5 Ktx/sec 196.5 Ktx/sec

serialize

schema format count new latency old latency new throughput old throughput
u32_u64_str bflatn_to_bsatn_fast_path 100 3.7±0.01µs 3.7±0.00µs 25.6 Mtx/sec 25.9 Mtx/sec
u32_u64_str bflatn_to_bsatn_slow_path 100 3.5±0.01µs 3.5±0.11µs 27.3 Mtx/sec 26.9 Mtx/sec
u32_u64_str bsatn 100 2.4±0.00µs 2.5±0.00µs 40.0 Mtx/sec 38.0 Mtx/sec
u32_u64_str json 100 4.8±0.01µs 4.8±0.13µs 19.8 Mtx/sec 19.9 Mtx/sec
u32_u64_str product_value 100 1015.6±0.58ns 1015.6±0.51ns 93.9 Mtx/sec 93.9 Mtx/sec
u32_u64_u64 bflatn_to_bsatn_fast_path 100 1249.2±2.97ns 1109.3±2.28ns 76.3 Mtx/sec 86.0 Mtx/sec
u32_u64_u64 bflatn_to_bsatn_slow_path 100 2.9±0.01µs 2.9±0.00µs 33.3 Mtx/sec 33.0 Mtx/sec
u32_u64_u64 bsatn 100 1656.2±32.35ns 1716.9±31.30ns 57.6 Mtx/sec 55.5 Mtx/sec
u32_u64_u64 json 100 3.1±0.02µs 3.1±0.03µs 30.5 Mtx/sec 31.2 Mtx/sec
u32_u64_u64 product_value 100 1009.3±0.55ns 1010.5±7.97ns 94.5 Mtx/sec 94.4 Mtx/sec
u64_u64_u32 bflatn_to_bsatn_fast_path 100 911.9±2.93ns 916.1±31.63ns 104.6 Mtx/sec 104.1 Mtx/sec
u64_u64_u32 bflatn_to_bsatn_slow_path 100 2.9±0.00µs 2.9±0.00µs 33.3 Mtx/sec 32.9 Mtx/sec
u64_u64_u32 bsatn 100 1707.7±33.28ns 1711.6±62.04ns 55.8 Mtx/sec 55.7 Mtx/sec
u64_u64_u32 json 100 3.1±0.09µs 3.2±0.12µs 30.7 Mtx/sec 29.7 Mtx/sec
u64_u64_u32 product_value 100 1008.9±0.68ns 1011.0±0.45ns 94.5 Mtx/sec 94.3 Mtx/sec

stdb_module_large_arguments

arg size new latency old latency new throughput old throughput
64KiB 95.6±4.69µs 88.3±10.12µs - -

stdb_module_print_bulk

line count new latency old latency new throughput old throughput
1 49.0±4.71µs 45.7±3.59µs - -
100 355.1±45.46µs 358.7±43.07µs - -
1000 2.9±0.35ms 2.4±0.52ms - -

remaining

name new latency old latency new throughput old throughput
sqlite/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 45.6±0.15µs 45.9±0.06µs 21.4 Ktx/sec 21.3 Ktx/sec
sqlite/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 40.4±0.19µs 40.5±0.11µs 24.2 Ktx/sec 24.1 Ktx/sec
sqlite/🧠/update_bulk/u32_u64_str/unique_0/load=2048/count=256 38.2±0.06µs 38.7±0.18µs 25.5 Ktx/sec 25.2 Ktx/sec
sqlite/🧠/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 34.8±0.40µs 35.5±0.15µs 28.0 Ktx/sec 27.5 Ktx/sec
stdb_module/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 1295.2±18.36µs 1268.3±17.39µs 772 tx/sec 788 tx/sec
stdb_module/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 993.0±6.25µs 970.7±9.71µs 1007 tx/sec 1030 tx/sec
stdb_raw/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 639.3±25.52µs 611.1±47.70µs 1564 tx/sec 1636 tx/sec
stdb_raw/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 482.6±13.37µs 475.4±9.30µs 2.0 Ktx/sec 2.1 Ktx/sec
stdb_raw/🧠/update_bulk/u32_u64_str/unique_0/load=2048/count=256 371.4±0.21µs 379.8±0.95µs 2.6 Ktx/sec 2.6 Ktx/sec
stdb_raw/🧠/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 336.1±0.22µs 342.0±0.27µs 2.9 Ktx/sec 2.9 Ktx/sec

@github-actions
Copy link

@github-actions github-actions bot commented on a854945 Jun 3, 2024

Choose a reason for hiding this comment

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

Callgrind benchmark results

Callgrind Benchmark Report

These benchmarks were run using callgrind,
an instruction-level profiler. They allow comparisons between sqlite (sqlite), SpacetimeDB running through a module (stdb_module), and the underlying SpacetimeDB data storage engine (stdb_raw). Callgrind emulates a CPU to collect the below estimates.

Measurement changes larger than five percent are in bold.

In-memory benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 6023 6025 -0.03% 6901 6897 0.06%
sqlite 5686 5686 0.00% 6120 6174 -0.87%

callgrind: filter

db schema indices count preload _column data_type total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str no_index 64 128 1 u64 79497 79499 -0.00% 79935 79933 0.00%
stdb_raw u32_u64_str no_index 64 128 2 string 121784 121786 -0.00% 122460 122354 0.09%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24242 24244 -0.01% 24564 24714 -0.61%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25281 25285 -0.02% 25665 25773 -0.42%
sqlite u32_u64_str no_index 64 128 2 string 143663 143663 0.00% 145137 145201 -0.04%
sqlite u32_u64_str no_index 64 128 1 u64 123004 123004 0.00% 124360 124268 0.07%
sqlite u32_u64_str btree_each_column 64 128 2 string 133526 133526 0.00% 135082 135282 -0.15%
sqlite u32_u64_str btree_each_column 64 128 1 u64 130321 130321 0.00% 131747 131891 -0.11%

callgrind: insert bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 64 128 886318 889811 -0.39% 939554 936439 0.33%
stdb_raw u32_u64_str btree_each_column 64 128 1013850 1017434 -0.35% 1037290 1042234 -0.47%
sqlite u32_u64_str unique_0 64 128 398417 398417 0.00% 420963 415277 1.37%
sqlite u32_u64_str btree_each_column 64 128 971490 971490 0.00% 1013688 1014904 -0.12%

callgrind: iterate

db schema indices count total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 152190 152192 -0.00% 152256 152230 0.02%
stdb_raw u32_u64_str unique_0 64 16164 16166 -0.01% 16226 16200 0.16%
sqlite u32_u64_str unique_0 1024 1046901 1046901 0.00% 1050299 1050341 -0.00%
sqlite u32_u64_str unique_0 64 75041 75047 -0.01% 76239 76217 0.03%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47438 47438 0.00% 50090 50090 0.00%
64 bsatn 25717 25717 0.00% 27961 27961 0.00%
16 bsatn 8118 8118 0.00% 9444 9444 0.00%
16 json 12142 12142 0.00% 14046 14046 0.00%

callgrind: update bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 1024 20378655 20424814 -0.23% 20906055 20827380 0.38%
stdb_raw u32_u64_str unique_0 64 128 1310476 1313255 -0.21% 1380386 1374961 0.39%
sqlite u32_u64_str unique_0 1024 1024 1802084 1802084 0.00% 1811554 1811354 0.01%
sqlite u32_u64_str unique_0 64 128 128620 128620 0.00% 131408 131488 -0.06%
On-disk benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 6388 6390 -0.03% 7312 7272 0.55%
sqlite 5718 5718 0.00% 6182 6202 -0.32%

callgrind: filter

db schema indices count preload _column data_type total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str no_index 64 128 1 u64 79862 79864 -0.00% 80480 80362 0.15%
stdb_raw u32_u64_str no_index 64 128 2 string 122128 122130 -0.00% 123096 122822 0.22%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24607 24609 -0.01% 24993 25155 -0.64%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25646 25650 -0.02% 26090 26230 -0.53%
sqlite u32_u64_str no_index 64 128 1 u64 124925 124925 0.00% 126517 126565 -0.04%
sqlite u32_u64_str no_index 64 128 2 string 145584 145584 0.00% 147306 147502 -0.13%
sqlite u32_u64_str btree_each_column 64 128 1 u64 132417 132417 0.00% 134205 134377 -0.13%
sqlite u32_u64_str btree_each_column 64 128 2 string 135591 135576 0.01% 137609 137814 -0.15%

callgrind: insert bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 64 128 836537 840170 -0.43% 857819 855024 0.33%
stdb_raw u32_u64_str btree_each_column 64 128 962321 967541 -0.54% 984795 990815 -0.61%
sqlite u32_u64_str unique_0 64 128 415965 415965 0.00% 438027 432549 1.27%
sqlite u32_u64_str btree_each_column 64 128 1022065 1022065 0.00% 1062279 1063873 -0.15%

callgrind: iterate

db schema indices count total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 152555 152557 -0.00% 152681 152631 0.03%
stdb_raw u32_u64_str unique_0 64 16538 16540 -0.01% 16664 16610 0.33%
sqlite u32_u64_str unique_0 1024 1049973 1049963 0.00% 1053767 1053673 0.01%
sqlite u32_u64_str unique_0 64 76823 76813 0.01% 78209 78091 0.15%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47438 47438 0.00% 50090 50090 0.00%
64 bsatn 25717 25717 0.00% 27961 27961 0.00%
16 bsatn 8118 8118 0.00% 9444 9444 0.00%
16 json 12142 12142 0.00% 14046 14046 0.00%

callgrind: update bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 1024 19336457 19378247 -0.22% 19944017 19849125 0.48%
stdb_raw u32_u64_str unique_0 64 128 1254153 1256804 -0.21% 1291675 1286158 0.43%
sqlite u32_u64_str unique_0 1024 1024 1809880 1809880 0.00% 1818618 1818674 -0.00%
sqlite u32_u64_str unique_0 64 128 132768 132768 0.00% 135708 135888 -0.13%

Please sign in to comment.