Skip to content

Commit

Permalink
commitlog: Return commit info (#1778)
Browse files Browse the repository at this point in the history
  • Loading branch information
kim authored Oct 1, 2024
1 parent efa9e0b commit ae17c6d
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
6 changes: 4 additions & 2 deletions crates/commitlog/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ impl Commit {
}

/// Serialize and write `self` to `out`.
pub fn write<W: Write>(&self, out: W) -> io::Result<()> {
///
/// Returns the crc32 checksum of the commit on success.
pub fn write<W: Write>(&self, out: W) -> io::Result<u32> {
let mut out = Crc32cWriter::new(out);

let min_tx_offset = self.min_tx_offset.to_le_bytes();
Expand All @@ -100,7 +102,7 @@ impl Commit {
let mut out = out.into_inner();
out.write_all(&crc.to_le_bytes())?;

Ok(())
Ok(crc)
}

/// Attempt to read one [`Commit`] from the given [`Read`]er.
Expand Down
10 changes: 5 additions & 5 deletions crates/commitlog/src/commitlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::{
Commit, Encode, Options,
};

pub use crate::segment::Committed;

/// A commitlog generic over the storage backend as well as the type of records
/// its [`Commit`]s contain.
#[derive(Debug)]
Expand Down Expand Up @@ -87,7 +89,7 @@ impl<R: Repo, T> Generic<R, T> {
/// fail with [`io::ErrorKind::AlreadyExists`]. Encountering this error kind
/// this means that something is seriously wrong underlying storage, and the
/// caller should stop writing to the log.
pub fn commit(&mut self) -> io::Result<usize> {
pub fn commit(&mut self) -> io::Result<Option<Committed>> {
self.panicked = true;
let writer = &mut self.head;
let sz = writer.commit.encoded_len();
Expand All @@ -102,15 +104,13 @@ impl<R: Repo, T> Generic<R, T> {
writer
};

let ret = if let Err(e) = writer.commit() {
let ret = writer.commit().or_else(|e| {
warn!("Commit failed: {e}");
// Nb.: Don't risk a panic by calling `self.sync()`.
// We already gave up on the last commit, and will retry it next time.
self.start_new_segment()?;
Err(e)
} else {
Ok(sz)
};
});
self.panicked = false;
ret
}
Expand Down
26 changes: 22 additions & 4 deletions crates/commitlog/src/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ impl Default for Header {
}
}

/// Metadata about a [`Commit`] which was successfully written via [`Writer::commit`].
pub struct Committed {
/// The range of transaction offsets included in the commit.
pub tx_range: Range<u64>,
/// The crc32 checksum of the commit's serialized form,
/// as written to the commitlog.
pub checksum: u32,
}

#[derive(Debug)]
pub struct Writer<W: io::Write> {
pub(crate) commit: Commit,
Expand Down Expand Up @@ -114,11 +123,15 @@ impl<W: io::Write> Writer<W> {
/// Write the current [`Commit`] to the underlying [`io::Write`].
///
/// Will do nothing if the current commit is empty (i.e. `Commit::n` is zero).
pub fn commit(&mut self) -> io::Result<()> {
/// In this case, `None` is returned.
///
/// Otherwise `Some` [`Committed`] is returned, providing some metadata about
/// the commit.
pub fn commit(&mut self) -> io::Result<Option<Committed>> {
if self.commit.n == 0 {
return Ok(());
return Ok(None);
}
self.commit.write(&mut self.inner)?;
let checksum = self.commit.write(&mut self.inner)?;
self.inner.flush()?;

let commit_len = self.commit.encoded_len() as u64;
Expand All @@ -130,12 +143,17 @@ impl<W: io::Write> Writer<W> {
})
});

let tx_range_start = self.commit.min_tx_offset;

self.bytes_written += commit_len;
self.commit.min_tx_offset += self.commit.n as u64;
self.commit.n = 0;
self.commit.records.clear();

Ok(())
Ok(Some(Committed {
tx_range: tx_range_start..self.commit.min_tx_offset,
checksum,
}))
}

/// The smallest transaction offset in this segment.
Expand Down

2 comments on commit ae17c6d

@github-actions
Copy link

@github-actions github-actions bot commented on ae17c6d Oct 1, 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 5395 5395 0.00% 5441 5441 0.00%
sqlite 5509 5509 0.00% 5893 5927 -0.57%

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 2 string 117799 117799 0.00% 118351 118353 -0.00%
stdb_raw u32_u64_str no_index 64 128 1 u64 75388 75388 0.00% 75784 75818 -0.04%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 24055 24055 0.00% 24451 24537 -0.35%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 23023 23023 0.00% 23351 23453 -0.43%
sqlite u32_u64_str no_index 64 128 2 string 144677 144619 0.04% 146251 146003 0.17%
sqlite u32_u64_str no_index 64 128 1 u64 124027 124017 0.01% 125349 125223 0.10%
sqlite u32_u64_str btree_each_column 64 128 2 string 134476 134418 0.04% 136166 136090 0.06%
sqlite u32_u64_str btree_each_column 64 128 1 u64 131344 131334 0.01% 132854 132826 0.02%

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 900150 900225 -0.01% 962878 962215 0.07%
stdb_raw u32_u64_str btree_each_column 64 128 1051678 1050087 0.15% 1091440 1125303 -3.01%
sqlite u32_u64_str unique_0 64 128 398158 398156 0.00% 413202 417990 -1.15%
sqlite u32_u64_str btree_each_column 64 128 983475 983483 -0.00% 1022549 1019677 0.28%

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 152681 152681 0.00% 152731 152765 -0.02%
stdb_raw u32_u64_str unique_0 64 15706 15706 0.00% 15752 15786 -0.22%
sqlite u32_u64_str unique_0 1024 1046653 1046653 0.00% 1049953 1049997 -0.00%
sqlite u32_u64_str unique_0 64 74799 74799 0.00% 75861 75789 0.10%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47374 47374 0.00% 50060 50132 -0.14%
64 bsatn 25716 25716 0.00% 27994 27994 0.00%
16 json 12126 12126 0.00% 14030 14098 -0.48%
16 bsatn 8117 8117 0.00% 9477 9511 -0.36%

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 20657809 20660751 -0.01% 21400253 21479653 -0.37%
stdb_raw u32_u64_str unique_0 64 128 1304658 1303704 0.07% 1387080 1360304 1.97%
sqlite u32_u64_str unique_0 1024 1024 1802091 1802101 -0.00% 1811167 1811547 -0.02%
sqlite u32_u64_str unique_0 64 128 128437 128447 -0.01% 131337 131221 0.09%
On-disk benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 5405 5405 0.00% 5451 5451 0.00%
sqlite 5551 5551 0.00% 6003 6033 -0.50%

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 2 string 117809 117809 0.00% 118309 118427 -0.10%
stdb_raw u32_u64_str no_index 64 128 1 u64 75398 75398 0.00% 75758 75824 -0.09%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 24066 24066 0.00% 24454 24540 -0.35%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 23033 23033 0.00% 23353 23455 -0.43%
sqlite u32_u64_str no_index 64 128 2 string 146598 146540 0.04% 148436 148356 0.05%
sqlite u32_u64_str no_index 64 128 1 u64 125948 125928 0.02% 127522 127476 0.04%
sqlite u32_u64_str btree_each_column 64 128 2 string 136598 136558 0.03% 138642 138724 -0.06%
sqlite u32_u64_str btree_each_column 64 128 1 u64 133440 133420 0.01% 135324 135330 -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 849048 849295 -0.03% 910974 910261 0.08%
stdb_raw u32_u64_str btree_each_column 64 128 1001200 1000199 0.10% 1072736 1073593 -0.08%
sqlite u32_u64_str unique_0 64 128 415695 415693 0.00% 429933 434851 -1.13%
sqlite u32_u64_str btree_each_column 64 128 1021736 1021740 -0.00% 1059614 1056632 0.28%

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 152691 152691 0.00% 152737 152771 -0.02%
stdb_raw u32_u64_str unique_0 64 15716 15716 0.00% 15762 15796 -0.22%
sqlite u32_u64_str unique_0 1024 1049721 1049721 0.00% 1053351 1053443 -0.01%
sqlite u32_u64_str unique_0 64 76571 76571 0.00% 77717 77841 -0.16%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47374 47374 0.00% 50060 50132 -0.14%
64 bsatn 25716 25716 0.00% 27994 27994 0.00%
16 json 12126 12126 0.00% 14030 14098 -0.48%
16 bsatn 8117 8117 0.00% 9477 9511 -0.36%

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 19363686 19366441 -0.01% 20223064 20278231 -0.27%
stdb_raw u32_u64_str unique_0 64 128 1256071 1256435 -0.03% 1339231 1342699 -0.26%
sqlite u32_u64_str unique_0 1024 1024 1809652 1809652 0.00% 1818376 1818234 0.01%
sqlite u32_u64_str unique_0 64 128 132563 132563 0.00% 135567 135573 -0.00%

@github-actions
Copy link

@github-actions github-actions bot commented on ae17c6d Oct 1, 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 💿 411.1±1.43ns 411.4±0.66ns - -
sqlite 🧠 404.5±2.11ns 399.0±1.56ns - -
stdb_raw 💿 627.1±1.06ns 632.0±0.91ns - -
stdb_raw 🧠 624.0±0.53ns 633.2±1.38ns - -

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 582.8±0.73µs 584.1±15.16µs 1715 tx/sec 1711 tx/sec
sqlite 💿 u32_u64_str unique_0 2048 256 150.4±0.96µs 146.9±0.42µs 6.5 Ktx/sec 6.6 Ktx/sec
sqlite 💿 u32_u64_u64 btree_each_column 2048 256 463.8±0.27µs 461.9±0.74µs 2.1 Ktx/sec 2.1 Ktx/sec
sqlite 💿 u32_u64_u64 unique_0 2048 256 137.4±0.57µs 132.4±0.18µs 7.1 Ktx/sec 7.4 Ktx/sec
sqlite 🧠 u32_u64_str btree_each_column 2048 256 448.5±0.44µs 443.2±0.69µs 2.2 Ktx/sec 2.2 Ktx/sec
sqlite 🧠 u32_u64_str unique_0 2048 256 124.2±0.71µs 117.5±0.58µs 7.9 Ktx/sec 8.3 Ktx/sec
sqlite 🧠 u32_u64_u64 btree_each_column 2048 256 364.5±0.59µs 363.2±0.73µs 2.7 Ktx/sec 2.7 Ktx/sec
sqlite 🧠 u32_u64_u64 unique_0 2048 256 107.0±0.56µs 102.1±1.10µs 9.1 Ktx/sec 9.6 Ktx/sec
stdb_raw 💿 u32_u64_str btree_each_column 2048 256 601.9±13.87µs 573.4±25.83µs 1661 tx/sec 1744 tx/sec
stdb_raw 💿 u32_u64_str unique_0 2048 256 479.9±44.31µs 483.8±23.19µs 2.0 Ktx/sec 2.0 Ktx/sec
stdb_raw 💿 u32_u64_u64 btree_each_column 2048 256 382.7±7.45µs 349.3±5.41µs 2.6 Ktx/sec 2.8 Ktx/sec
stdb_raw 💿 u32_u64_u64 unique_0 2048 256 362.0±8.69µs 313.6±23.15µs 2.7 Ktx/sec 3.1 Ktx/sec
stdb_raw 🧠 u32_u64_str btree_each_column 2048 256 304.2±0.16µs 307.1±0.15µs 3.2 Ktx/sec 3.2 Ktx/sec
stdb_raw 🧠 u32_u64_str unique_0 2048 256 240.3±0.24µs 237.7±0.29µs 4.1 Ktx/sec 4.1 Ktx/sec
stdb_raw 🧠 u32_u64_u64 btree_each_column 2048 256 241.9±0.24µs 242.8±0.10µs 4.0 Ktx/sec 4.0 Ktx/sec
stdb_raw 🧠 u32_u64_u64 unique_0 2048 256 219.3±0.27µs 217.7±0.40µs 4.5 Ktx/sec 4.5 Ktx/sec

iterate

db on disk schema indices new latency old latency new throughput old throughput
sqlite 💿 u32_u64_str unique_0 22.4±0.07µs 20.1±0.06µs 43.6 Ktx/sec 48.6 Ktx/sec
sqlite 💿 u32_u64_u64 unique_0 20.9±0.12µs 18.6±0.07µs 46.8 Ktx/sec 52.6 Ktx/sec
sqlite 🧠 u32_u64_str unique_0 19.8±0.12µs 17.6±0.06µs 49.3 Ktx/sec 55.4 Ktx/sec
sqlite 🧠 u32_u64_u64 unique_0 18.5±0.09µs 16.1±0.03µs 52.7 Ktx/sec 60.6 Ktx/sec
stdb_raw 💿 u32_u64_str unique_0 4.7±0.00µs 3.8±0.00µs 205.7 Ktx/sec 255.2 Ktx/sec
stdb_raw 💿 u32_u64_u64 unique_0 4.6±0.00µs 3.7±0.00µs 210.4 Ktx/sec 263.7 Ktx/sec
stdb_raw 🧠 u32_u64_str unique_0 4.7±0.00µs 3.8±0.00µs 205.8 Ktx/sec 254.7 Ktx/sec
stdb_raw 🧠 u32_u64_u64 unique_0 4.6±0.00µs 3.7±0.00µs 210.8 Ktx/sec 263.8 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 69.0±0.08µs 69.5±0.18µs 14.2 Ktx/sec 14.0 Ktx/sec
sqlite 💿 u64 index 2048 256 65.9±0.10µs 64.2±0.02µs 14.8 Ktx/sec 15.2 Ktx/sec
sqlite 🧠 string index 2048 256 66.0±0.12µs 66.4±0.21µs 14.8 Ktx/sec 14.7 Ktx/sec
sqlite 🧠 u64 index 2048 256 60.7±0.05µs 59.3±0.10µs 16.1 Ktx/sec 16.5 Ktx/sec
stdb_raw 💿 string index 2048 256 4.9±0.00µs 4.8±0.00µs 200.7 Ktx/sec 204.7 Ktx/sec
stdb_raw 💿 u64 index 2048 256 4.8±0.00µs 4.8±0.00µs 201.4 Ktx/sec 201.6 Ktx/sec
stdb_raw 🧠 string index 2048 256 4.9±0.00µs 4.8±0.00µs 201.2 Ktx/sec 204.6 Ktx/sec
stdb_raw 🧠 u64 index 2048 256 4.8±0.00µs 4.8±0.00µs 201.6 Ktx/sec 201.7 Ktx/sec

serialize

schema format count new latency old latency new throughput old throughput
u32_u64_str bflatn_to_bsatn_fast_path 100 3.2±0.02µs 3.3±0.01µs 29.5 Mtx/sec 29.3 Mtx/sec
u32_u64_str bflatn_to_bsatn_slow_path 100 3.0±0.04µs 3.0±0.01µs 31.3 Mtx/sec 31.5 Mtx/sec
u32_u64_str bsatn 100 2.5±0.02µs 2.3±0.00µs 38.4 Mtx/sec 41.1 Mtx/sec
u32_u64_str bsatn 100 40.5±0.16ns 40.5±0.07ns 2.3 Gtx/sec 2.3 Gtx/sec
u32_u64_str json 100 5.5±0.03µs 5.9±0.05µs 17.3 Mtx/sec 16.2 Mtx/sec
u32_u64_str json 100 7.4±0.03µs 8.3±0.02µs 13.0 Mtx/sec 11.4 Mtx/sec
u32_u64_str product_value 100 1017.7±4.97ns 1015.8±0.68ns 93.7 Mtx/sec 93.9 Mtx/sec
u32_u64_u64 bflatn_to_bsatn_fast_path 100 1223.9±34.03ns 1125.9±1.50ns 77.9 Mtx/sec 84.7 Mtx/sec
u32_u64_u64 bflatn_to_bsatn_slow_path 100 2.5±0.00µs 2.5±0.00µs 38.9 Mtx/sec 38.7 Mtx/sec
u32_u64_u64 bsatn 100 1718.8±35.96ns 1688.7±37.86ns 55.5 Mtx/sec 56.5 Mtx/sec
u32_u64_u64 bsatn 100 28.9±0.09ns 39.4±0.08ns 3.2 Gtx/sec 2.4 Gtx/sec
u32_u64_u64 json 100 3.4±0.13µs 3.4±0.08µs 28.1 Mtx/sec 27.8 Mtx/sec
u32_u64_u64 json 100 5.0±0.03µs 4.9±0.00µs 19.0 Mtx/sec 19.4 Mtx/sec
u32_u64_u64 product_value 100 1017.0±1.88ns 1014.8±1.02ns 93.8 Mtx/sec 94.0 Mtx/sec
u64_u64_u32 bflatn_to_bsatn_fast_path 100 904.0±2.18ns 895.8±0.52ns 105.5 Mtx/sec 106.5 Mtx/sec
u64_u64_u32 bflatn_to_bsatn_slow_path 100 2.5±0.01µs 2.5±0.00µs 38.6 Mtx/sec 38.7 Mtx/sec
u64_u64_u32 bsatn 100 1707.8±107.85ns 1736.9±33.34ns 55.8 Mtx/sec 54.9 Mtx/sec
u64_u64_u32 bsatn 100 707.4±0.33ns 749.5±0.55ns 134.8 Mtx/sec 127.2 Mtx/sec
u64_u64_u32 json 100 3.5±0.03µs 3.5±0.15µs 27.0 Mtx/sec 27.1 Mtx/sec
u64_u64_u32 json 100 4.9±0.00µs 5.0±0.04µs 19.3 Mtx/sec 18.9 Mtx/sec
u64_u64_u32 product_value 100 1019.1±1.82ns 1014.4±0.74ns 93.6 Mtx/sec 94.0 Mtx/sec

stdb_module_large_arguments

arg size new latency old latency new throughput old throughput
64KiB 107.7±12.90µs 115.9±11.85µs - -

stdb_module_print_bulk

line count new latency old latency new throughput old throughput
1 47.0±8.78µs 52.3±7.53µs - -
100 593.8±7.24µs 599.4±5.98µs - -
1000 3.4±0.16ms 5.4±0.05ms - -

remaining

name new latency old latency new throughput old throughput
special/db_game/circles/load=10 298.0±3.78µs 297.4±2.57µs - -
special/db_game/circles/load=100 292.3±3.51µs 297.0±3.43µs - -
special/db_game/ia_loop/load=10 0.0±0.00ns 0.0±0.00ns - -
special/db_game/ia_loop/load=100 0.0±0.00ns 0.0±0.00ns - -
sqlite/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 53.6±0.24µs 51.8±0.25µs 18.2 Ktx/sec 18.9 Ktx/sec
sqlite/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 45.8±0.06µs 44.4±0.13µs 21.3 Ktx/sec 22.0 Ktx/sec
sqlite/🧠/update_bulk/u32_u64_str/unique_0/load=2048/count=256 39.2±0.15µs 37.8±0.13µs 24.9 Ktx/sec 25.8 Ktx/sec
sqlite/🧠/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 35.8±0.09µs 33.7±0.08µs 27.3 Ktx/sec 29.0 Ktx/sec
stdb_module/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 1272.3±9.58µs 1281.7±9.87µs 785 tx/sec 780 tx/sec
stdb_module/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 1030.1±7.97µs 1030.0±7.20µs 970 tx/sec 970 tx/sec
stdb_raw/💿/update_bulk/u32_u64_str/unique_0/load=2048/count=256 637.3±16.83µs 643.5±18.81µs 1569 tx/sec 1554 tx/sec
stdb_raw/💿/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 503.2±7.24µs 488.9±8.00µs 1987 tx/sec 2045 tx/sec
stdb_raw/🧠/update_bulk/u32_u64_str/unique_0/load=2048/count=256 375.4±0.34µs 367.1±0.45µs 2.6 Ktx/sec 2.7 Ktx/sec
stdb_raw/🧠/update_bulk/u32_u64_u64/unique_0/load=2048/count=256 340.2±0.42µs 335.0±0.23µs 2.9 Ktx/sec 2.9 Ktx/sec

Please sign in to comment.