Skip to content

Commit

Permalink
Remove problematic debug assertions (#2010)
Browse files Browse the repository at this point in the history
  • Loading branch information
gefjon authored Nov 26, 2024
1 parent 94c66c9 commit 8075567
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 79 deletions.
39 changes: 0 additions & 39 deletions crates/table/src/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ struct FixedHeader {
///
/// Unallocated row slots store valid-unconstrained bytes, i.e. are never uninit.
present_rows: FixedBitSet,

#[cfg(debug_assertions)]
fixed_row_size: Size,
}

impl MemoryUsage for FixedHeader {
Expand All @@ -171,18 +168,11 @@ impl MemoryUsage for FixedHeader {
last,
num_rows,
present_rows,
// MEMUSE: it's just a u16, ok to ignore
#[cfg(debug_assertions)]
fixed_row_size: _,
} = self;
next_free.heap_usage() + last.heap_usage() + num_rows.heap_usage() + present_rows.heap_usage()
}
}

#[cfg(debug_assertions)]
static_assert_size!(FixedHeader, 18);

#[cfg(not(debug_assertions))]
static_assert_size!(FixedHeader, 16);

impl FixedHeader {
Expand All @@ -196,19 +186,9 @@ impl FixedHeader {
last: PageOffset::VAR_LEN_NULL,
num_rows: 0,
present_rows: FixedBitSet::new(PageOffset::PAGE_END.idx().div_ceil(fixed_row_size.len())),
#[cfg(debug_assertions)]
fixed_row_size,
}
}

#[cfg(debug_assertions)]
fn debug_check_fixed_row_size(&self, fixed_row_size: Size) {
assert_eq!(self.fixed_row_size, fixed_row_size);
}

#[cfg(not(debug_assertions))]
fn debug_check_fixed_row_size(&self, _: Size) {}

/// Set the (fixed) row starting at `offset`
/// and lasting `fixed_row_size` as `present`.
#[inline]
Expand All @@ -221,15 +201,13 @@ impl FixedHeader {
/// and lasting `fixed_row_size` is `present` or not.
#[inline]
fn set_row_presence(&mut self, offset: PageOffset, fixed_row_size: Size, present: bool) {
self.debug_check_fixed_row_size(fixed_row_size);
self.present_rows.set(offset / fixed_row_size, present);
}

/// Returns whether the (fixed) row starting at `offset`
/// and lasting `fixed_row_size` is present or not.
#[inline]
fn is_row_present(&self, offset: PageOffset, fixed_row_size: Size) -> bool {
self.debug_check_fixed_row_size(fixed_row_size);
self.present_rows.get(offset / fixed_row_size)
}

Expand Down Expand Up @@ -442,13 +420,11 @@ impl FixedView<'_> {
/// in an expected state, i.e. initialized where required by the row type,
/// and with `VarLenRef`s that point to valid granules and with correct lengths.
pub fn get_row_mut(&mut self, start: PageOffset, fixed_row_size: Size) -> &mut Bytes {
self.header.debug_check_fixed_row_size(fixed_row_size);
&mut self.fixed_row_data[start.range(fixed_row_size)]
}

/// Returns a shared view of the row from `start` lasting `fixed_row_size` number of bytes.
fn get_row(&mut self, start: PageOffset, fixed_row_size: Size) -> &Bytes {
self.header.debug_check_fixed_row_size(fixed_row_size);
&self.fixed_row_data[start.range(fixed_row_size)]
}

Expand Down Expand Up @@ -1198,8 +1174,6 @@ impl Page {
/// where the fixed size part is `fixed_row_size` bytes large,
/// and the variable part requires `num_granules`.
pub fn has_space_for_row(&self, fixed_row_size: Size, num_granules: usize) -> bool {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

// Determine the gap remaining after allocating for the fixed part.
let gap_remaining = gap_remaining_size(self.header.var.first, self.header.fixed.last);
let gap_avail_for_granules = if self.header.fixed.next_free.has() {
Expand Down Expand Up @@ -1257,7 +1231,6 @@ impl Page {
) -> Result<PageOffset, Error> {
// Allocate the fixed-len row.
let fixed_row_size = Size(fixed_row.len() as u16);
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

// SAFETY: Caller promised that `fixed_row.len()` uses the right `fixed_row_size`
// and we trust that others have too.
Expand Down Expand Up @@ -1300,8 +1273,6 @@ impl Page {
/// `fixed_row_size` must be equal to the value passed
/// to all other methods ever invoked on `self`.
pub unsafe fn alloc_fixed_len(&mut self, fixed_row_size: Size) -> Result<PageOffset, Error> {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

self.alloc_fixed_len_from_freelist(fixed_row_size)
.or_else(|| self.alloc_fixed_len_from_gap(fixed_row_size))
.ok_or(Error::InsufficientFixedLenSpace { need: fixed_row_size })
Expand Down Expand Up @@ -1352,7 +1323,6 @@ impl Page {
/// It is the caller's responsibility to ensure that `PageOffset`s derived from
/// this iterator are valid when used to do anything `unsafe`.
fn iter_fixed_len_from(&self, fixed_row_size: Size, starting_from: PageOffset) -> FixedLenRowsIter<'_> {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);
let idx = starting_from / fixed_row_size;
FixedLenRowsIter {
idx_iter: self.header.fixed.present_rows.iter_set_from(idx),
Expand All @@ -1369,7 +1339,6 @@ impl Page {
/// It is the caller's responsibility to ensure that `PageOffset`s derived from
/// this iterator are valid when used to do anything `unsafe`.
pub fn iter_fixed_len(&self, fixed_row_size: Size) -> FixedLenRowsIter<'_> {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);
FixedLenRowsIter {
idx_iter: self.header.fixed.present_rows.iter_set(),
fixed_row_size,
Expand Down Expand Up @@ -1423,8 +1392,6 @@ impl Page {
var_len_visitor: &impl VarLenMembers,
blob_store: &mut dyn BlobStore,
) -> BlobNumBytes {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

// We're modifying the page, so clear the unmodified hash.
self.header.unmodified_hash = None;

Expand Down Expand Up @@ -1473,8 +1440,6 @@ impl Page {
fixed_row_size: Size,
var_len_visitor: &impl VarLenMembers,
) -> usize {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

let fixed_row = self.get_row_data(fixed_row_offset, fixed_row_size);
// SAFETY:
// - Caller promised that `fixed_row_offset` is a valid row.
Expand Down Expand Up @@ -1515,8 +1480,6 @@ impl Page {
blob_store: &mut dyn BlobStore,
mut filter: impl FnMut(&Page, PageOffset) -> bool,
) -> ControlFlow<(), PageOffset> {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

for row_offset in self
.iter_fixed_len_from(fixed_row_size, starting_from)
// Only copy rows satisfying the predicate `filter`.
Expand Down Expand Up @@ -1560,8 +1523,6 @@ impl Page {
var_len_visitor: &impl VarLenMembers,
blob_store: &mut dyn BlobStore,
) -> bool {
self.header.fixed.debug_check_fixed_row_size(fixed_row_size);

// SAFETY: Caller promised that `starting_from` points to a valid row
// consistent with `fixed_row_size` which was also
// claimed to be consistent with `var_len_visitor` and `self`.
Expand Down
40 changes: 0 additions & 40 deletions crates/table/src/pointer_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,46 +166,6 @@ impl MemoryUsage for PointerMap {

static_assert_size!(PointerMap, 80);

// Provides some type invariant checks.
// These are only used as sanity checks in the debug profile, and e.g., in tests.
#[cfg(debug_assertions)]
impl PointerMap {
#[allow(unused)]
fn maintains_invariants(&self) -> bool {
self.maintains_map_invariant() && self.maintains_colliders_invariant()
}

#[allow(unused)]
fn maintains_colliders_invariant(&self) -> bool {
self.colliders.iter().enumerate().all(|(idx, slot)| {
slot.len() >= 2 || slot.is_empty() && self.emptied_collider_slots.contains(&ColliderSlotIndex::new(idx))
})
}

#[allow(unused)]
fn maintains_map_invariant(&self) -> bool {
self.map.values().all(|poc| {
let collider = poc.as_collider();
poc.is_ptr()
|| self.colliders[collider.idx()].len() >= 2 && !self.emptied_collider_slots.contains(&collider)
})
}
}

// `debug_assert!` conditions are always typechecked, even when debug assertions are disabled.
// This means that we would see a build error in release mode
// due to `PointerMap::maintains_invariants` being undefined.
// Easily solved by including a stub definition.
#[cfg(not(debug_assertions))]
#[allow(dead_code)]
impl PointerMap {
fn maintains_invariants(&self) -> bool {
unreachable!(
"`PointerMap::maintains_invariants` is only meaningfully defined when building with debug assertions."
)
}
}

// Provides the public API.
impl PointerMap {
/// The number of colliding hashes in the map.
Expand Down

2 comments on commit 8075567

@github-actions
Copy link

@github-actions github-actions bot commented on 8075567 Nov 26, 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 8075567 Nov 26, 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 6426 6426 0.00% 6544 6544 0.00%
sqlite 5585 5585 0.00% 6113 6113 0.00%

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 76579 76579 0.00% 77007 77007 0.00%
stdb_raw u32_u64_str no_index 64 128 2 string 118821 118821 0.00% 119515 119547 -0.03%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25111 25114 -0.01% 25621 25660 -0.15%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24078 24078 0.00% 24522 24518 0.02%
sqlite u32_u64_str no_index 64 128 2 string 144695 144695 0.00% 146165 146165 0.00%
sqlite u32_u64_str no_index 64 128 1 u64 124044 124044 0.00% 125280 125276 0.00%
sqlite u32_u64_str btree_each_column 64 128 1 u64 131361 131361 0.00% 132821 132817 0.00%
sqlite u32_u64_str btree_each_column 64 128 2 string 134494 134494 0.00% 136140 136144 -0.00%

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 878215 880451 -0.25% 897709 932615 -3.74%
stdb_raw u32_u64_str btree_each_column 64 128 1029243 1026671 0.25% 1086873 1084305 0.24%
sqlite u32_u64_str unique_0 64 128 398320 398320 0.00% 417708 417704 0.00%
sqlite u32_u64_str btree_each_column 64 128 983637 983655 -0.00% 1020547 1020569 -0.00%

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 153810 153810 0.00% 153926 153926 0.00%
stdb_raw u32_u64_str unique_0 64 16835 16835 0.00% 16935 16935 0.00%
sqlite u32_u64_str unique_0 1024 1068281 1068281 0.00% 1071651 1071651 0.00%
sqlite u32_u64_str unique_0 64 76273 76267 0.01% 77417 77411 0.01%

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% 50214 50214 0.00%
64 bsatn 25509 25509 0.00% 27753 27753 0.00%
16 bsatn 8200 8200 0.00% 9560 9560 0.00%
16 json 12188 12188 0.00% 14126 14126 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 20561569 20557141 0.02% 21040603 21037357 0.02%
stdb_raw u32_u64_str unique_0 64 128 1288352 1288415 -0.00% 1354920 1353867 0.08%
sqlite u32_u64_str unique_0 1024 1024 1802182 1802182 0.00% 1811352 1811352 0.00%
sqlite u32_u64_str unique_0 64 128 128528 128528 0.00% 131244 131244 0.00%
On-disk benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 6431 6431 0.00% 6557 6557 0.00%
sqlite 5627 5627 0.00% 6211 6211 0.00%

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 76584 76584 0.00% 76988 76988 0.00%
stdb_raw u32_u64_str no_index 64 128 2 string 118826 118826 0.00% 119548 119512 0.03%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 25117 25115 0.01% 25619 25601 0.07%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 24083 24083 0.00% 24503 24503 0.00%
sqlite u32_u64_str no_index 64 128 1 u64 125965 125965 0.00% 127565 127561 0.00%
sqlite u32_u64_str no_index 64 128 2 string 146616 146616 0.00% 148486 148478 0.01%
sqlite u32_u64_str btree_each_column 64 128 2 string 136616 136616 0.00% 138800 138792 0.01%
sqlite u32_u64_str btree_each_column 64 128 1 u64 133457 133457 0.00% 135391 135379 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 827945 826987 0.12% 877563 845675 3.77%
stdb_raw u32_u64_str btree_each_column 64 128 976292 977801 -0.15% 1033146 1034389 -0.12%
sqlite u32_u64_str unique_0 64 128 415857 415857 0.00% 434579 434583 -0.00%
sqlite u32_u64_str btree_each_column 64 128 1021908 1021908 0.00% 1057628 1057624 0.00%

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 153815 153815 0.00% 153915 153915 0.00%
stdb_raw u32_u64_str unique_0 64 16840 16840 0.00% 16944 16940 0.02%
sqlite u32_u64_str unique_0 1024 1071355 1071349 0.00% 1075099 1075093 0.00%
sqlite u32_u64_str unique_0 64 78039 78039 0.00% 79395 79395 0.00%

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% 50214 50214 0.00%
64 bsatn 25509 25509 0.00% 27753 27753 0.00%
16 bsatn 8200 8200 0.00% 9560 9560 0.00%
16 json 12188 12188 0.00% 14126 14126 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 19046651 19045907 0.00% 19571089 19570857 0.00%
stdb_raw u32_u64_str unique_0 64 128 1240290 1240373 -0.01% 1303974 1304129 -0.01%
sqlite u32_u64_str unique_0 1024 1024 1809743 1809743 0.00% 1818413 1818405 0.00%
sqlite u32_u64_str unique_0 64 128 132654 132654 0.00% 135598 135586 0.01%

Please sign in to comment.