Skip to content

Commit

Permalink
Fix subscription benchmarks by fixing `create_table_for_test_with_the…
Browse files Browse the repository at this point in the history
…_works` (#2027)
  • Loading branch information
Centril authored Dec 5, 2024
1 parent d9de1e3 commit 6f22261
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/bench/benches/subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ fn eval(c: &mut Criterion) {
&raw.db,
&tx,
None,
Compression::Brotli,
Compression::None,
)))
})
});
Expand Down
3 changes: 2 additions & 1 deletion crates/core/src/db/relational_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,8 +841,9 @@ impl RelationalDB {
access: StAccess,
) -> Result<TableId, DBError> {
let mut module_def_builder = RawModuleDefV9Builder::new();

let mut table_builder = module_def_builder
.build_table_with_new_type(name, ProductType::from_iter(schema.iter().cloned()), true)
.build_table_with_new_type_for_tests(name, ProductType::from_iter(schema.iter().cloned()), true)
.with_access(access.into());

for columns in indexes {
Expand Down
50 changes: 50 additions & 0 deletions crates/lib/src/db/raw_def/v9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,11 +479,61 @@ impl RawModuleDefV9Builder {
custom_ordering: bool,
) -> RawTableDefBuilder {
let table_name = table_name.into();

let product_type_ref = self.add_algebraic_type([], table_name.clone(), product_type.into(), custom_ordering);

self.build_table(table_name, product_type_ref)
}

/// Build a new table with a product type, for testing.
/// Adds the type to the module.
pub fn build_table_with_new_type_for_tests(
&mut self,
table_name: impl Into<RawIdentifier>,
mut product_type: spacetimedb_sats::ProductType,
custom_ordering: bool,
) -> RawTableDefBuilder {
self.add_expand_product_type_for_tests(&mut 0, &mut product_type);

self.build_table_with_new_type(table_name, product_type, custom_ordering)
}

fn add_expand_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut AlgebraicType) {
if ty.is_valid_for_client_type_use() {
return;
}

match ty {
AlgebraicType::Product(prod_ty) => self.add_expand_product_type_for_tests(name_gen, prod_ty),
AlgebraicType::Sum(sum_type) => {
if let Some(wrapped) = sum_type.as_option_mut() {
self.add_expand_type_for_tests(name_gen, wrapped);
} else {
for elem in sum_type.variants.iter_mut() {
self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
}
}
}
AlgebraicType::Array(ty) => {
self.add_expand_type_for_tests(name_gen, &mut ty.elem_ty);
return;
}
_ => return,
}

// Make the type into a ref.
let name = *name_gen;
let add_ty = core::mem::replace(ty, AlgebraicType::U8);
*ty = AlgebraicType::Ref(self.add_algebraic_type([], format!("gen_{name}"), add_ty, true));
*name_gen += 1;
}

fn add_expand_product_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut ProductType) {
for elem in ty.elements.iter_mut() {
self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
}
}

/// Add a type to the typespace, along with a type alias declaring its name.
/// This method should only be use for `AlgebraicType`s not corresponding to a Rust
/// type that implements `SpacetimeType`.
Expand Down
29 changes: 22 additions & 7 deletions crates/sats/src/sum_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,32 @@ impl SumType {
/// If the type does look like a structural option type, returns the type `T`.
pub fn as_option(&self) -> Option<&AlgebraicType> {
match &*self.variants {
[first, second]
if second.is_unit() // Done first to avoid pointer indirection when it doesn't matter.
&& first.has_name(OPTION_SOME_TAG)
&& second.has_name(OPTION_NONE_TAG) =>
{
Some(&first.algebraic_type)
}
[first, second] if Self::are_variants_option(first, second) => Some(&first.algebraic_type),
_ => None,
}
}

/// Check whether this sum type is a structural option type.
///
/// A structural option type has `some(T)` as its first variant and `none` as its second.
/// That is, `{ some(T), none }` or `some: T | none` depending on your notation.
/// Note that `some` and `none` are lowercase, unlike Rust's `Option`.
/// Order matters, and an option type with these variants in the opposite order will not be recognized.
///
/// If the type does look like a structural option type, returns the type `T`.
pub fn as_option_mut(&mut self) -> Option<&mut AlgebraicType> {
match &mut *self.variants {
[first, second] if Self::are_variants_option(first, second) => Some(&mut first.algebraic_type),
_ => None,
}
}

fn are_variants_option(first: &SumTypeVariant, second: &SumTypeVariant) -> bool {
second.is_unit() // Done first to avoid pointer indirection when it doesn't matter.
&& first.has_name(OPTION_SOME_TAG)
&& second.has_name(OPTION_NONE_TAG)
}

/// Check whether this sum type is a structural option type.
///
/// A structural option type has `some(T)` as its first variant and `none` as its second.
Expand Down

2 comments on commit 6f22261

@github-actions
Copy link

@github-actions github-actions bot commented on 6f22261 Dec 5, 2024

Choose a reason for hiding this comment

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

Benchmarking failed. Please check the workflow run for details.

@github-actions
Copy link

@github-actions github-actions bot commented on 6f22261 Dec 5, 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 6396 6396 0.00% 6532 6532 0.00%
sqlite 5609 5609 0.00% 5987 6015 -0.47%

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 74672 74672 0.00% 75256 75420 -0.22%
stdb_raw u32_u64_str no_index 64 128 2 string 116906 116914 -0.01% 117732 117940 -0.18%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25080 25081 -0.00% 25774 25771 0.01%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24048 24048 0.00% 24632 24776 -0.58%
sqlite u32_u64_str no_index 64 128 2 string 144415 144415 0.00% 145853 145837 0.01%
sqlite u32_u64_str no_index 64 128 1 u64 123763 123763 0.00% 125099 124907 0.15%
sqlite u32_u64_str btree_each_column 64 128 1 u64 131080 131080 0.00% 132608 132504 0.08%
sqlite u32_u64_str btree_each_column 64 128 2 string 134222 134222 0.00% 135812 135832 -0.01%

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 880468 881594 -0.13% 927208 927476 -0.03%
stdb_raw u32_u64_str btree_each_column 64 128 1027467 1029361 -0.18% 1051431 1053101 -0.16%
sqlite u32_u64_str unique_0 64 128 399360 399366 -0.00% 415774 418334 -0.61%
sqlite u32_u64_str btree_each_column 64 128 984611 984611 0.00% 1020037 1023405 -0.33%

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 138372 138372 0.00% 138506 138482 0.02%
stdb_raw u32_u64_str unique_0 64 15797 15797 0.00% 15919 15915 0.03%
sqlite u32_u64_str unique_0 1024 1042718 1042718 0.00% 1046078 1046038 0.00%
sqlite u32_u64_str unique_0 64 74710 74710 0.00% 75934 75806 0.17%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47528 47528 0.00% 50282 50282 0.00%
64 bsatn 25509 25509 0.00% 27719 27719 0.00%
16 bsatn 8200 8200 0.00% 9560 9560 0.00%
16 json 12188 12188 0.00% 14160 14160 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 20567572 20130299 2.17% 21087768 20588343 2.43%
stdb_raw u32_u64_str unique_0 64 128 1287928 1287061 0.07% 1354982 1320957 2.58%
sqlite u32_u64_str unique_0 1024 1024 1802137 1802137 0.00% 1811347 1811273 0.00%
sqlite u32_u64_str unique_0 64 128 128540 128540 0.00% 131484 131336 0.11%
On-disk benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 6401 6401 0.00% 6549 6549 0.00%
sqlite 5651 5651 0.00% 6055 6091 -0.59%

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 74677 74677 0.00% 75193 75349 -0.21%
stdb_raw u32_u64_str no_index 64 128 2 string 116903 116919 -0.01% 117717 117861 -0.12%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25085 25085 0.00% 25679 25743 -0.25%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24053 24053 0.00% 24601 24709 -0.44%
sqlite u32_u64_str no_index 64 128 1 u64 125684 125684 0.00% 127368 127200 0.13%
sqlite u32_u64_str no_index 64 128 2 string 146336 146336 0.00% 148178 148026 0.10%
sqlite u32_u64_str btree_each_column 64 128 2 string 136418 136418 0.00% 138500 138444 0.04%
sqlite u32_u64_str btree_each_column 64 128 1 u64 133176 133176 0.00% 135132 134988 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 829943 830143 -0.02% 875287 875167 0.01%
stdb_raw u32_u64_str btree_each_column 64 128 979010 980922 -0.19% 1032892 1037274 -0.42%
sqlite u32_u64_str unique_0 64 128 416914 416914 0.00% 432798 435364 -0.59%
sqlite u32_u64_str btree_each_column 64 128 1023158 1023158 0.00% 1058116 1062324 -0.40%

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 138369 138377 -0.01% 138483 138467 0.01%
stdb_raw u32_u64_str unique_0 64 15802 15802 0.00% 15912 15892 0.13%
sqlite u32_u64_str unique_0 1024 1045796 1045796 0.00% 1049508 1049528 -0.00%
sqlite u32_u64_str unique_0 64 76486 76486 0.00% 77858 77830 0.04%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47528 47528 0.00% 50282 50282 0.00%
64 bsatn 25509 25509 0.00% 27719 27719 0.00%
16 bsatn 8200 8200 0.00% 9560 9560 0.00%
16 json 12188 12188 0.00% 14160 14160 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 19063296 19059120 0.02% 19616986 19627540 -0.05%
stdb_raw u32_u64_str unique_0 64 128 1241624 1240513 0.09% 1307518 1306115 0.11%
sqlite u32_u64_str unique_0 1024 1024 1809785 1809791 -0.00% 1818467 1818339 0.01%
sqlite u32_u64_str unique_0 64 128 132687 132687 0.00% 135811 135643 0.12%

Please sign in to comment.