diff --git a/Cargo.toml b/Cargo.toml index 89a96c8..2128560 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -mace = { git = "https://github.com/abbycin/mace" } +mace-kv = { git = "https://github.com/abbycin/mace" } clap = { version = "4.5.48", features = ["derive"] } rand = "0.9.2" log = "0.4.22" diff --git a/README.md b/README.md index 5e2c2fd..560c8c2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ --- -## get performance (cold get) +## random get performance (cold get) ![mace_get](./scripts/mace_get.png) @@ -15,8 +15,14 @@ --- -# mixed perfomance +# mixed perfomance (hot get) ![mace_mixed](./scripts/mace_mixed.png) -![rockdb_mixed](./scripts/rocksdb_mixed.png) \ No newline at end of file +![rockdb_mixed](./scripts/rocksdb_mixed.png) + +# sequential scan perfomance (cold scan) + +![mace_scan](./scripts/mace_scan.png) + +![rocksdb_scan](./scripts/rocksdb_scan.png) \ No newline at end of file diff --git a/rocksdb/main.cpp b/rocksdb/main.cpp index c2f8254..0ab578b 100644 --- a/rocksdb/main.cpp +++ b/rocksdb/main.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -44,7 +46,7 @@ int main(int argc, char *argv[]) { .path = "/tmp/rocksdb_tmp", }; - app.add_option("-m,--mode", args.mode, "Mode: insert, get, mixed"); + app.add_option("-m,--mode", args.mode, "Mode: insert, get, mixed, scan"); app.add_option("-t,--threads", args.threads, "Threads"); app.add_option("-k,--key-size", args.key_size, "Key Size"); app.add_option("-v,--value-size", args.value_size, "Value Size"); @@ -65,7 +67,7 @@ int main(int argc, char *argv[]) { return 1; } - if (args.mode != "insert" && args.mode != "get" && args.mode != "mixed") { + if (args.mode != "insert" && args.mode != "get" && args.mode != "mixed" && args.mode != "scan") { fmt::println("Error: Invalid mode"); return 1; } @@ -102,7 +104,6 @@ int main(int argc, char *argv[]) { options.enable_pipelined_write = true; options.env->SetBackgroundThreads(4, rocksdb::Env::Priority::HIGH); - auto ropt = rocksdb::ReadOptions(); auto wopt = rocksdb::WriteOptions(); wopt.no_slowdown = true; // wopt.disableWAL = true; @@ -130,15 +131,16 @@ int main(int argc, char *argv[]) { tmp.resize(args.key_size, 'x'); key.emplace_back(std::move(tmp)); } - if (args.random) { + if (args.mode == "get" || args.random) { std::shuffle(keys.begin(), keys.end(), gen); } keys.emplace_back(std::move(key)); } + auto *handle = handles[0]; - if (args.mode == "get") { + if (args.mode == "get" || args.mode == "scan") { auto *kv = db->BeginTransaction(wopt); for (size_t tid = 0; tid < args.threads; ++tid) { auto *tk = &keys[tid]; @@ -159,8 +161,11 @@ int main(int argc, char *argv[]) { handle = handles[0]; for (size_t tid = 0; tid < args.threads; ++tid) { auto *tk = &keys[tid]; - wg.emplace_back([&] { + wg.emplace_back([&, tid] { std::string rval(args.value_size, '0'); + auto prefix = std::format("key_{}", tid); + auto ropt = rocksdb::ReadOptions(); + barrier.arrive_and_wait(); if (mtx.try_lock()) { b = nm::Instant::now(); @@ -194,6 +199,13 @@ int main(int argc, char *argv[]) { kv->Commit(); delete kv; } + } else if (args.mode == "scan") { + auto *iter = db->NewIterator(ropt); + iter->Seek(prefix); + while (iter->Valid()) { + iter->Next(); + } + delete iter; } total_op.fetch_add(args.iterations, std::memory_order::relaxed); }); diff --git a/scripts/mace.sh b/scripts/mace.sh index 4ccd042..71124de 100755 --- a/scripts/mace.sh +++ b/scripts/mace.sh @@ -32,6 +32,12 @@ function samples() { echo "mixed threads $i ksz ${kv_sz[j]} vsz ${kv_sz[j+1]} fail" exit 1 fi + ./target/release/kv_bench --path /home/abby/mace_bench --threads $i --iterations $cnt --mode scan --key-size ${kv_sz[j]} --value-size ${kv_sz[j+1]} --insert-ratio 30 + if test $? -ne 0 + then + echo "mixed threads $i ksz ${kv_sz[j]} vsz ${kv_sz[j+1]} fail" + exit 1 + fi done done } diff --git a/scripts/mace_get.png b/scripts/mace_get.png index b91d2a5..57dca00 100644 Binary files a/scripts/mace_get.png and b/scripts/mace_get.png differ diff --git a/scripts/mace_insert.png b/scripts/mace_insert.png index f85c346..85463c5 100644 Binary files a/scripts/mace_insert.png and b/scripts/mace_insert.png differ diff --git a/scripts/mace_mixed.png b/scripts/mace_mixed.png index 6e9d819..008da1b 100644 Binary files a/scripts/mace_mixed.png and b/scripts/mace_mixed.png differ diff --git a/scripts/mace_scan.png b/scripts/mace_scan.png new file mode 100644 index 0000000..906a5f4 Binary files /dev/null and b/scripts/mace_scan.png differ diff --git a/scripts/plot.py b/scripts/plot.py index 7a63081..e2bf344 100644 --- a/scripts/plot.py +++ b/scripts/plot.py @@ -5,8 +5,12 @@ import sys def real_mode(m): if m == "mixed": - return "MIXED (70% Get, 30% Insert)" - return m.upper() + return "Mixed (70% Get, 30% Insert)" + elif m == "get": + return "Random Get" + elif m == "scan": + return "Sequential Scan" + return m.capitalize() name = sys.argv[1] prefix = name.split(".")[0] diff --git a/scripts/rocksdb.sh b/scripts/rocksdb.sh index 35bcf93..63b8713 100755 --- a/scripts/rocksdb.sh +++ b/scripts/rocksdb.sh @@ -31,6 +31,12 @@ function samples() { echo "mixed threads $i ksz ${kv_sz[j]} vsz ${kv_sz[j+1]} fail" exit 1 fi + ./build/release/rocksdb_bench --path /home/abby/rocksdb_tmp --threads $i --iterations $cnt --mode scan --key-size ${kv_sz[j]} --value-size ${kv_sz[j+1]} --insert-ratio 30 + if test $? -ne 0 + then + echo "mixed threads $i ksz ${kv_sz[j]} vsz ${kv_sz[j+1]} fail" + exit 1 + fi done done } diff --git a/scripts/rocksdb_get.png b/scripts/rocksdb_get.png index 231f0e1..9f77b96 100644 Binary files a/scripts/rocksdb_get.png and b/scripts/rocksdb_get.png differ diff --git a/scripts/rocksdb_insert.png b/scripts/rocksdb_insert.png index 162a513..38d57d8 100644 Binary files a/scripts/rocksdb_insert.png and b/scripts/rocksdb_insert.png differ diff --git a/scripts/rocksdb_mixed.png b/scripts/rocksdb_mixed.png index 5265469..3cf7f00 100644 Binary files a/scripts/rocksdb_mixed.png and b/scripts/rocksdb_mixed.png differ diff --git a/scripts/rocksdb_scan.png b/scripts/rocksdb_scan.png new file mode 100644 index 0000000..31a7625 Binary files /dev/null and b/scripts/rocksdb_scan.png differ diff --git a/src/main.rs b/src/main.rs index abdc862..8bbdfa8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,7 +49,7 @@ struct Args { fn main() { #[cfg(target_os = "linux")] { - Logger::init().add_file("/Data/x.log", true); + Logger::init().add_file("/tmp/x.log", true); log::set_max_level(log::LevelFilter::Info); } let args = Args::parse(); @@ -81,7 +81,7 @@ fn main() { opt.sync_on_write = false; opt.over_provision = true; // large value will use lots of memeory opt.inline_size = args.blob_size; - opt.tmp_store = args.mode != "get"; + opt.tmp_store = args.mode != "get" && args.mode != "scan"; let mut saved = opt.clone(); saved.tmp_store = false; let mut db = Mace::new(opt.validate().unwrap()).unwrap(); @@ -96,13 +96,13 @@ fn main() { key.resize(args.key_size, b'x'); tk.push(key); } - if args.random { + if args.random || args.mode == "get" { tk.shuffle(&mut rng); } keys.push(tk); } - if args.mode == "get" { + if args.mode == "get" || args.mode == "scan" { let pre_tx = db.begin().unwrap(); (0..args.threads).for_each(|tid| { for i in 0..args.iterations { @@ -130,6 +130,7 @@ fn main() { let insert_ratio = args.insert_ratio; let st = start_time.clone(); let val = value.clone(); + let prefix = format!("key_{tid}"); std::thread::spawn(move || { // coreid::bind_core(tid); @@ -169,6 +170,13 @@ fn main() { } } } + "scan" => { + let view = db.view().unwrap(); + let iter = view.seek(prefix); + for x in iter { + std::hint::black_box(x); + } + } _ => panic!("Invalid mode"), }