Skip to content

Commit 8422ad6

Browse files
authored
Merge pull request #117 from fjall-rs/perf/skip-range-key-cmps
Skip superfluous range bound key comparisons
2 parents 7e86856 + 36e1673 commit 8422ad6

36 files changed

+190
-610
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ quick_cache = { version = "0.6.5", default-features = false, features = [] }
3737
rustc-hash = "2.0.0"
3838
self_cell = "1.0.4"
3939
tempfile = "3.12.0"
40-
value-log = { version = "1.6.0", default-features = false, features = [] }
40+
value-log = { version = "1.7.2", default-features = false, features = [] }
4141
varint-rs = "2.2.0"
4242
xxhash-rust = { version = "0.8.12", features = ["xxh3"] }
4343

benches/tli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use criterion::{criterion_group, criterion_main, Criterion};
22
use lsm_tree::segment::{
3-
block_index::KeyedBlockIndex, value_block::BlockOffset, value_block::CachePolicy,
3+
block::offset::BlockOffset, block_index::KeyedBlockIndex, value_block::CachePolicy,
44
};
55

66
fn tli_find_item(c: &mut Criterion) {

src/abstract.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,16 @@ pub trait AbstractTree {
106106
/// Returns `None` if the level does not exist (if idx >= 7).
107107
fn level_segment_count(&self, idx: usize) -> Option<usize>;
108108

109+
/// Returns the amount of disjoint runs in L0.
110+
///
111+
/// Can be used to determine whether to write stall.
112+
fn l0_run_count(&self) -> usize;
113+
109114
/// Returns the amount of blob files currently in the tree.
110115
fn blob_file_count(&self) -> usize {
111116
0
112117
}
113118

114-
/// Returns `true` if the first level is disjoint.
115-
fn is_first_level_disjoint(&self) -> bool;
116-
117119
/// Approximates the amount of items in the tree.
118120
fn approximate_len(&self) -> usize;
119121

src/blob_tree/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ impl BlobTree {
230230
}
231231

232232
impl AbstractTree for BlobTree {
233+
fn l0_run_count(&self) -> usize {
234+
self.index.l0_run_count()
235+
}
236+
233237
fn blob_file_count(&self) -> usize {
234238
self.blobs.segment_count()
235239
}
@@ -256,10 +260,6 @@ impl AbstractTree for BlobTree {
256260
self.index.sealed_memtable_count()
257261
}
258262

259-
fn is_first_level_disjoint(&self) -> bool {
260-
self.index.is_first_level_disjoint()
261-
}
262-
263263
#[doc(hidden)]
264264
fn verify(&self) -> crate::Result<usize> {
265265
let index_tree_sum = self.index.verify()?;

src/blob_tree/value.rs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use crate::coding::{Decode, DecodeError, Encode, EncodeError};
66
use byteorder::{ReadBytesExt, WriteBytesExt};
7-
use std::io::{Read, Write};
7+
use std::io::{Cursor, Read, Write};
88
use value_log::{Slice, UserValue, ValueHandle};
99
use varint_rs::{VarintReader, VarintWriter};
1010

@@ -22,46 +22,25 @@ pub enum MaybeInlineValue {
2222
Indirect { vhandle: ValueHandle, size: u32 },
2323
}
2424

25-
impl Encode for ValueHandle {
26-
fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
27-
writer.write_u64_varint(self.offset)?;
28-
writer.write_u64_varint(self.segment_id)?;
29-
Ok(())
30-
}
31-
}
32-
33-
impl Decode for ValueHandle {
34-
fn decode_from<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
35-
let offset = reader.read_u64_varint()?;
36-
let segment_id = reader.read_u64_varint()?;
37-
Ok(Self { segment_id, offset })
38-
}
39-
}
40-
4125
const TAG_INLINE: u8 = 0;
4226
const TAG_INDIRECT: u8 = 1;
4327

4428
impl MaybeInlineValue {
4529
pub fn from_slice(bytes: &Slice) -> Result<Self, DecodeError> {
46-
let tag = *bytes.first().expect("vhandle bytes should not be empty");
30+
let mut cursor = Cursor::new(&**bytes);
4731

48-
match tag {
32+
match cursor.read_u8()? {
4933
TAG_INLINE => {
50-
// TODO: 3.0.0 because the length field is varint encoded
51-
// TODO: we need to get the amount of bytes the integer needs
52-
// TODO: maybe not use varint encoding here... (breaking)
53-
let len_size = {
54-
let mut reader = bytes.get(1..).expect("see above");
55-
let len = reader.read_u32_varint()?;
56-
match len {
57-
0..=0x7F => 1, // Fits in 7 bits
58-
0x80..=0x3FFF => 2, // Fits in 14 bits
59-
0x4000..=0x001F_FFFF => 3, // Fits in 21 bits
60-
0x0020_0000..=0x0FFF_FFFF => 4, // Fits in 28 bits
61-
_ => 5, // Fits in 35 bits
62-
}
34+
// NOTE: Truncation is OK because we are only at the first couple
35+
// of bytes of the slice
36+
#[allow(clippy::cast_possible_truncation)]
37+
let size_len = {
38+
let pos_before = cursor.position() as usize;
39+
let _ = cursor.read_u32_varint()?;
40+
let pos_after = cursor.position() as usize;
41+
pos_after - pos_before
6342
};
64-
let slice = bytes.slice((1 + len_size)..);
43+
let slice = bytes.slice((1 + size_len)..);
6544
Ok(Self::Inline(slice))
6645
}
6746
TAG_INDIRECT => {

src/block_cache.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// (found in the LICENSE-* files in the repository)
44

55
use crate::either::Either::{self, Left, Right};
6+
use crate::segment::block::offset::BlockOffset;
67
use crate::segment::id::GlobalSegmentId;
7-
use crate::segment::value_block::BlockOffset;
88
use crate::segment::{block_index::IndexBlock, value_block::ValueBlock};
99
use quick_cache::Weighter;
1010
use quick_cache::{sync::Cache, Equivalent};

src/coding.rs

Lines changed: 0 additions & 116 deletions
This file was deleted.

src/compaction/fifo.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,16 @@ mod tests {
122122
config::Config,
123123
descriptor_table::FileDescriptorTable,
124124
file::LEVELS_MANIFEST_FILE,
125-
key_range::KeyRange,
126125
level_manifest::LevelManifest,
127126
segment::{
127+
block::offset::BlockOffset,
128128
block_index::{two_level_index::TwoLevelBlockIndex, BlockIndexImpl},
129129
file_offsets::FileOffsets,
130130
meta::{Metadata, SegmentId},
131-
value_block::BlockOffset,
132131
Segment, SegmentInner,
133132
},
134133
time::unix_timestamp,
135-
HashSet,
134+
HashSet, KeyRange,
136135
};
137136
use std::sync::Arc;
138137
use test_log::test;

src/compaction/leveled.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
use super::{Choice, CompactionStrategy, Input as CompactionInput};
66
use crate::{
77
config::Config,
8-
key_range::KeyRange,
98
level_manifest::{hidden_set::HiddenSet, level::Level, LevelManifest},
109
segment::Segment,
1110
windows::{GrowingWindowsExt, ShrinkingWindowsExt},
12-
HashSet, SegmentId,
11+
HashSet, KeyRange, SegmentId,
1312
};
1413

1514
// TODO: for a disjoint set of segments, we could just take the first and last segment and use their first and last key respectively
@@ -387,17 +386,16 @@ mod tests {
387386
block_cache::BlockCache,
388387
compaction::{CompactionStrategy, Input as CompactionInput},
389388
descriptor_table::FileDescriptorTable,
390-
key_range::KeyRange,
391389
level_manifest::LevelManifest,
392390
segment::{
391+
block::offset::BlockOffset,
393392
block_index::{two_level_index::TwoLevelBlockIndex, BlockIndexImpl},
394393
file_offsets::FileOffsets,
395394
meta::{Metadata, SegmentId},
396-
value_block::BlockOffset,
397395
Segment, SegmentInner,
398396
},
399397
time::unix_timestamp,
400-
Config, HashSet,
398+
Config, HashSet, KeyRange,
401399
};
402400
use std::{path::Path, sync::Arc};
403401
use test_log::test;

src/compaction/maintenance.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,15 @@ mod tests {
8787
config::Config,
8888
descriptor_table::FileDescriptorTable,
8989
file::LEVELS_MANIFEST_FILE,
90-
key_range::KeyRange,
9190
level_manifest::LevelManifest,
9291
segment::{
92+
block::offset::BlockOffset,
9393
block_index::{two_level_index::TwoLevelBlockIndex, BlockIndexImpl},
9494
file_offsets::FileOffsets,
9595
meta::Metadata,
96-
value_block::BlockOffset,
9796
Segment, SegmentInner,
9897
},
98+
KeyRange,
9999
};
100100
use std::sync::Arc;
101101
use test_log::test;

src/compaction/tiered.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,15 @@ mod tests {
136136
config::Config,
137137
descriptor_table::FileDescriptorTable,
138138
file::LEVELS_MANIFEST_FILE,
139-
key_range::KeyRange,
140139
level_manifest::LevelManifest,
141140
segment::{
141+
block::offset::BlockOffset,
142142
block_index::{two_level_index::TwoLevelBlockIndex, BlockIndexImpl},
143143
file_offsets::FileOffsets,
144144
meta::{Metadata, SegmentId},
145-
value_block::BlockOffset,
146145
Segment, SegmentInner,
147146
},
148-
HashSet, SeqNo,
147+
HashSet, KeyRange, SeqNo,
149148
};
150149
use std::sync::Arc;
151150
use test_log::test;

0 commit comments

Comments
 (0)