Skip to content

Commit 38ec5e9

Browse files
committed
Add RocksDB TPCC comparison path
1 parent 2d25a9f commit 38ec5e9

3 files changed

Lines changed: 86 additions & 53 deletions

File tree

src/storage/rocksdb.rs

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414

1515
use crate::errors::DatabaseError;
16-
use crate::storage::table_codec::{Bytes, TableCodec};
16+
use crate::storage::table_codec::TableCodec;
1717
use crate::storage::{
1818
CheckpointableStorage, InnerIter, Storage, Transaction, TransactionIsolationLevel,
1919
};
@@ -665,6 +665,7 @@ macro_rules! impl_transaction {
665665
read_opts.set_prefix_same_as_start(true);
666666
}
667667
}
668+
set_iterate_upper_bound(&mut read_opts, max);
668669

669670
let mut iter = self.tx.raw_iterator_opt(read_opts);
670671
match &min {
@@ -679,7 +680,6 @@ macro_rules! impl_transaction {
679680
}
680681

681682
Ok($iter {
682-
upper: owned_bound(max),
683683
iter,
684684
advanced: false,
685685
done: false,
@@ -698,7 +698,6 @@ impl_transaction!(RocksTransaction, RocksIter);
698698
impl_transaction!(OptimisticRocksTransaction, OptimisticRocksIter);
699699

700700
pub struct OptimisticRocksIter<'txn, 'iter> {
701-
upper: Bound<Bytes>,
702701
iter: DBRawIteratorWithThreadMode<'iter, rocksdb::Transaction<'txn, OptimisticTransactionDB>>,
703702
advanced: bool,
704703
done: bool,
@@ -707,17 +706,11 @@ pub struct OptimisticRocksIter<'txn, 'iter> {
707706
impl InnerIter for OptimisticRocksIter<'_, '_> {
708707
#[inline]
709708
fn try_next(&mut self) -> Result<Option<crate::storage::KeyValueRef<'_>>, DatabaseError> {
710-
next(
711-
&mut self.iter,
712-
&self.upper,
713-
&mut self.advanced,
714-
&mut self.done,
715-
)
709+
next(&mut self.iter, &mut self.advanced, &mut self.done)
716710
}
717711
}
718712

719713
pub struct RocksIter<'txn, 'iter> {
720-
upper: Bound<Bytes>,
721714
iter: DBRawIteratorWithThreadMode<
722715
'iter,
723716
rocksdb::Transaction<'txn, TransactionDB<rocksdb::MultiThreaded>>,
@@ -729,19 +722,27 @@ pub struct RocksIter<'txn, 'iter> {
729722
impl InnerIter for RocksIter<'_, '_> {
730723
#[inline]
731724
fn try_next(&mut self) -> Result<Option<crate::storage::KeyValueRef<'_>>, DatabaseError> {
732-
next(
733-
&mut self.iter,
734-
&self.upper,
735-
&mut self.advanced,
736-
&mut self.done,
737-
)
725+
next(&mut self.iter, &mut self.advanced, &mut self.done)
726+
}
727+
}
728+
729+
#[inline]
730+
fn set_iterate_upper_bound(read_opts: &mut ReadOptions, upper: Bound<&[u8]>) {
731+
match upper {
732+
Bound::Included(bytes) => {
733+
let mut exclusive_upper = Vec::with_capacity(bytes.len() + 1);
734+
exclusive_upper.extend_from_slice(bytes);
735+
exclusive_upper.push(0);
736+
read_opts.set_iterate_upper_bound(exclusive_upper);
737+
}
738+
Bound::Excluded(bytes) => read_opts.set_iterate_upper_bound(bytes),
739+
Bound::Unbounded => {}
738740
}
739741
}
740742

741743
#[inline]
742744
fn next<'a, D: rocksdb::DBAccess>(
743745
iter: &'a mut DBRawIteratorWithThreadMode<'_, D>,
744-
upper: &Bound<Bytes>,
745746
advanced: &mut bool,
746747
done: &mut bool,
747748
) -> Result<Option<crate::storage::KeyValueRef<'a>>, DatabaseError> {
@@ -762,28 +763,11 @@ fn next<'a, D: rocksdb::DBAccess>(
762763
iter.status()?;
763764
return Ok(None);
764765
};
765-
let upper_bound_check = match upper {
766-
Bound::Included(upper) => key <= upper.as_slice(),
767-
Bound::Excluded(upper) => key < upper.as_slice(),
768-
Bound::Unbounded => true,
769-
};
770-
if !upper_bound_check {
771-
*done = true;
772-
return Ok(None);
773-
}
774766

775767
*advanced = true;
776768
Ok(Some((key, value)))
777769
}
778770

779-
fn owned_bound(bound: Bound<&[u8]>) -> Bound<Bytes> {
780-
match bound {
781-
Bound::Included(bytes) => Bound::Included(bytes.to_vec()),
782-
Bound::Excluded(bytes) => Bound::Excluded(bytes.to_vec()),
783-
Bound::Unbounded => Bound::Unbounded,
784-
}
785-
}
786-
787771
#[cfg(all(test, not(target_arch = "wasm32")))]
788772
mod test {
789773
use crate::catalog::{ColumnCatalog, ColumnDesc, ColumnRef, TableName};
@@ -792,8 +776,8 @@ mod test {
792776
use crate::expression::range_detacher::Range;
793777
use crate::storage::rocksdb::RocksStorage;
794778
use crate::storage::{
795-
IndexImplEnum, IndexImplParams, IndexIter, IndexIterState, IterBounds, PrimaryKeyIndexImpl,
796-
Storage, Transaction,
779+
IndexImplEnum, IndexImplParams, IndexIter, IndexIterState, InnerIter, IterBounds,
780+
PrimaryKeyIndexImpl, Storage, Transaction,
797781
};
798782
use crate::types::index::{IndexMeta, IndexType};
799783
use crate::types::tuple::Tuple;
@@ -837,6 +821,34 @@ mod test {
837821
Ok(())
838822
}
839823

824+
#[test]
825+
fn test_rocksdb_range_uses_iterate_upper_bound() -> Result<(), DatabaseError> {
826+
let temp_dir = TempDir::new().expect("unable to create temporary working directory");
827+
let storage = RocksStorage::new(temp_dir.path())?;
828+
let mut transaction = storage.transaction()?;
829+
830+
transaction.set(b"a", b"1")?;
831+
transaction.set(b"b", b"2")?;
832+
transaction.set(b"b\0", b"3")?;
833+
transaction.set(b"c", b"4")?;
834+
835+
let mut inclusive_iter = transaction.range(Bound::Included(b"a"), Bound::Included(b"b"))?;
836+
let mut inclusive_keys = Vec::new();
837+
while let Some((key, _)) = inclusive_iter.try_next()? {
838+
inclusive_keys.push(key.to_vec());
839+
}
840+
assert_eq!(inclusive_keys, vec![b"a".to_vec(), b"b".to_vec()]);
841+
842+
let mut exclusive_iter = transaction.range(Bound::Included(b"a"), Bound::Excluded(b"b"))?;
843+
let mut exclusive_keys = Vec::new();
844+
while let Some((key, _)) = exclusive_iter.try_next()? {
845+
exclusive_keys.push(key.to_vec());
846+
}
847+
assert_eq!(exclusive_keys, vec![b"a".to_vec()]);
848+
849+
Ok(())
850+
}
851+
840852
#[test]
841853
fn test_in_rocksdb_storage_works_with_data() -> Result<(), DatabaseError> {
842854
let temp_dir = TempDir::new().expect("unable to create temporary working directory");

tpcc/src/backend/kitesql_rocksdb.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ use super::{
1717
};
1818
use crate::TpccError;
1919
use kite_sql::db::{prepare, DBTransaction, DataBaseBuilder, Database, TransactionIter};
20-
use kite_sql::storage::rocksdb::{RocksStorage, RocksTransaction};
21-
use kite_sql::storage::Transaction;
20+
use kite_sql::storage::rocksdb::{OptimisticRocksStorage, RocksStorage};
21+
use kite_sql::storage::{Storage, Transaction};
2222
use kite_sql::types::tuple::Tuple;
2323

24-
pub struct KiteSqlRocksDbBackend {
25-
database: Database<RocksStorage>,
24+
pub type KiteSqlRocksDbBackend = KiteSqlRocksBackend<RocksStorage>;
25+
pub type KiteSqlOptimisticRocksDbBackend = KiteSqlRocksBackend<OptimisticRocksStorage>;
26+
pub type KiteSqlRocksDbTransaction<'a> = KiteSqlRocksTransaction<'a, RocksStorage>;
27+
28+
pub struct KiteSqlRocksBackend<S: Storage> {
29+
database: Database<S>,
2630
}
2731

2832
impl KiteSqlRocksDbBackend {
@@ -33,7 +37,19 @@ impl KiteSqlRocksDbBackend {
3337
.build_rocksdb()?,
3438
})
3539
}
40+
}
3641

42+
impl KiteSqlOptimisticRocksDbBackend {
43+
pub fn new(path: &str, rocksdb_stats: bool) -> Result<Self, TpccError> {
44+
Ok(Self {
45+
database: DataBaseBuilder::path(path)
46+
.storage_statistics(rocksdb_stats)
47+
.build_optimistic()?,
48+
})
49+
}
50+
}
51+
52+
impl<S: Storage> KiteSqlRocksBackend<S> {
3753
fn prepare_spec_groups(
3854
&self,
3955
specs: &[Vec<StatementSpec>],
@@ -53,16 +69,16 @@ impl KiteSqlRocksDbBackend {
5369
Ok(groups)
5470
}
5571

56-
fn start_transaction(&self) -> Result<KiteSqlRocksDbTransaction<'_>, TpccError> {
57-
Ok(KiteSqlRocksDbTransaction {
72+
fn start_transaction(&self) -> Result<KiteSqlRocksTransaction<'_, S>, TpccError> {
73+
Ok(KiteSqlRocksTransaction {
5874
inner: self.database.new_transaction()?,
5975
})
6076
}
6177
}
6278

63-
impl BackendControl for KiteSqlRocksDbBackend {
79+
impl<S: Storage> BackendControl for KiteSqlRocksBackend<S> {
6480
type Transaction<'a>
65-
= KiteSqlRocksDbTransaction<'a>
81+
= KiteSqlRocksTransaction<'a, S>
6682
where
6783
Self: 'a;
6884

@@ -84,23 +100,23 @@ impl BackendControl for KiteSqlRocksDbBackend {
84100
}
85101
}
86102

87-
impl SimpleExecutor for KiteSqlRocksDbBackend {
103+
impl<S: Storage> SimpleExecutor for KiteSqlRocksBackend<S> {
88104
fn execute_batch(&self, sql: &str) -> Result<(), TpccError> {
89105
self.database.run(sql)?.done()?;
90106
Ok(())
91107
}
92108
}
93109

94-
pub struct KiteSqlRocksDbTransaction<'a> {
95-
inner: DBTransaction<'a, RocksStorage>,
110+
pub struct KiteSqlRocksTransaction<'a, S: Storage> {
111+
inner: DBTransaction<'a, S>,
96112
}
97113

98-
impl<'a> KiteSqlRocksDbTransaction<'a> {
114+
impl<'a, S: Storage> KiteSqlRocksTransaction<'a, S> {
99115
pub(crate) fn execute_raw<'b>(
100116
&'b mut self,
101117
statement: &PreparedStatement,
102118
params: &[DbParam],
103-
) -> Result<RocksTxnResult<'b, 'a>, TpccError> {
119+
) -> Result<KiteSqlTxnResult<'b, S::TransactionType<'a>>, TpccError> {
104120
let PreparedStatement::KiteSql { statement, .. } = statement else {
105121
return Err(TpccError::InvalidBackend);
106122
};
@@ -110,7 +126,7 @@ impl<'a> KiteSqlRocksDbTransaction<'a> {
110126
}
111127
}
112128

113-
impl<'a> BackendTransaction for KiteSqlRocksDbTransaction<'a> {
129+
impl<'a, S: Storage> BackendTransaction for KiteSqlRocksTransaction<'a, S> {
114130
fn query_one(
115131
&mut self,
116132
statement: &PreparedStatement,
@@ -202,5 +218,3 @@ impl<T: Transaction> Iterator for KiteSqlTxnResult<'_, T> {
202218
self.0.next().map(|item| item.map_err(TpccError::from))
203219
}
204220
}
205-
206-
pub(crate) type RocksTxnResult<'a, 'txn> = KiteSqlTxnResult<'a, RocksTransaction<'txn>>;

tpcc/src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use crate::backend::dual::DualBackend;
1616
use crate::backend::kitesql_lmdb::KiteSqlLmdbBackend;
17-
use crate::backend::kitesql_rocksdb::KiteSqlRocksDbBackend;
17+
use crate::backend::kitesql_rocksdb::{KiteSqlOptimisticRocksDbBackend, KiteSqlRocksDbBackend};
1818
use crate::backend::sqlite::{SqliteBackend, SqliteProfile};
1919
use crate::backend::{
2020
BackendControl, BackendTransaction, ColumnType, PreparedStatement, StatementSpec,
@@ -36,6 +36,7 @@ use rand::prelude::ThreadRng;
3636
use rand::Rng;
3737
use std::fs;
3838
use std::path::Path;
39+
#[cfg(any(feature = "pprof", test))]
3940
use std::path::PathBuf;
4041
use std::time::{Duration, Instant};
4142

@@ -125,6 +126,7 @@ struct Args {
125126
#[derive(Copy, Clone, Debug, ValueEnum)]
126127
enum BackendKind {
127128
KitesqlRocksdb,
129+
KitesqlOptimisticRocksdb,
128130
KitesqlLmdb,
129131
Sqlite,
130132
Dual,
@@ -141,6 +143,11 @@ fn main() -> Result<(), TpccError> {
141143
let backend = KiteSqlRocksDbBackend::new(&args.path, args.rocksdb_stats)?;
142144
run_tpcc(&backend, &args, &mut rng)
143145
}
146+
BackendKind::KitesqlOptimisticRocksdb => {
147+
reset_db_path(Path::new(&args.path))?;
148+
let backend = KiteSqlOptimisticRocksDbBackend::new(&args.path, args.rocksdb_stats)?;
149+
run_tpcc(&backend, &args, &mut rng)
150+
}
144151
BackendKind::KitesqlLmdb => {
145152
reset_db_path(Path::new(&args.path))?;
146153
let backend = KiteSqlLmdbBackend::new(&args.path)?;

0 commit comments

Comments
 (0)