diff --git a/rocksdb/CMakeLists.txt b/rocksdb/CMakeLists.txt new file mode 100644 index 0000000..74a1317 --- /dev/null +++ b/rocksdb/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 4.0) +project(rockseb_bench) + +set(CMAKE_CXX_STANDARD 23) + +add_executable(rockseb_bench main.cpp + instant.h) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") +target_compile_options(rockseb_bench PRIVATE "-flto") +target_link_libraries(rockseb_bench rocksdb) diff --git a/rocksdb/instant.h b/rocksdb/instant.h new file mode 100644 index 0000000..b3f1c3a --- /dev/null +++ b/rocksdb/instant.h @@ -0,0 +1,55 @@ +#ifndef INSTANT_20231013102058 +#define INSTANT_20231013102058 + +#include + +namespace nm +{ +class Instant { +public: + static Instant now() + { + return { std::chrono::steady_clock::now() }; + } + + auto elapse_usec() + { + return diff().count() / 1e3; + } + + auto elapse_ms() + { + return diff().count() / 1e6; + } + + auto elapse_sec() + { + return diff().count() / 1e9; + } + + auto elapse_min() + { + return elapse_sec() / 60.0; + } + + void reset() + { + *this = now(); + } + +private: + using timepoint = std::chrono::steady_clock::time_point; + Instant(timepoint now) : tp_ { now } + { + } + + auto diff() -> std::chrono::duration + { + return std::chrono::steady_clock::now() - tp_; + } + + timepoint tp_; +}; +} // namespace nm + +#endif // INSTANT_20231013102058 diff --git a/rocksdb/main.cpp b/rocksdb/main.cpp new file mode 100644 index 0000000..55f975a --- /dev/null +++ b/rocksdb/main.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "instant.h" + +int main() +{ + std::string db_root = "/home/abby/rocksdb_tmp"; + std::filesystem::remove_all(db_root); + rocksdb::Options options; + options.disable_auto_compactions = true; + options.create_if_missing = true; + options.max_write_buffer_number = 10; + options.target_file_size_base = 64 << 20; + options.write_buffer_size = 64 << 20; + options.level0_file_num_compaction_trigger = 500; + options.max_bytes_for_level_base = 2 << 30; + constexpr size_t count = 100000; + constexpr size_t workers = 4; + auto ropt = rocksdb::ReadOptions(); + auto wopt = rocksdb::WriteOptions(); + std::vector wg; + std::vector> keys {}; + rocksdb::OptimisticTransactionDB *db; + std::cout << "db_root " << db_root << '\n'; + auto s = rocksdb::OptimisticTransactionDB::Open(options, db_root, &db); + assert(s.ok()); + std::string val(1024, 'x'); + + for (size_t tid = 0; tid < workers; ++tid) { + std::vector key {}; + + for (size_t i = 0; i < count; ++i) { + auto tmp = std::format("key_{}_{}", tid, i); + tmp.resize(1024, 'x'); + key.push_back(std::move(tmp)); + } + keys.emplace_back(std::move(key)); + } + + for (size_t tid = 0; tid < workers; ++tid) { + auto ks = &keys[tid]; + wg.emplace_back( + [&] + { + for (auto &x : *ks) { + auto kv = db->BeginTransaction(wopt); + kv->Put(x, x); + kv->Commit(); + delete kv; + } + }); + } + + for (auto &w : wg) { + w.join(); + } + + delete db; + wg.clear(); + + auto sts = + rocksdb::OptimisticTransactionDB::Open(options, db_root, &db); + assert(sts.ok()); + std::barrier g { workers }; + auto b = nm::Instant::now(); + std::mutex mtx {}; + std::atomic operation { 0 }; + + for (size_t tid = 0; tid < workers; ++tid) { + auto ks = &keys[tid]; + wg.emplace_back( + [&] + { + g.arrive_and_wait(); + + std::string val; + if (mtx.try_lock()) { + b = nm::Instant::now(); + mtx.unlock(); + } + + for (auto &x : *ks) { + auto kv = db->BeginTransaction(wopt); + kv->Get(ropt, x, &val); + kv->Commit(); + delete kv; + } + operation.fetch_add(count, + std::memory_order_relaxed); + }); + } + + for (auto &w : wg) { + w.join(); + } + + printf("thread %ld\niterations %ld\nkey_size %ld\nvalue_size %ld\nops: " + "%.2f\n", + workers, + count, + keys[0][0].size(), + val.size(), + static_cast(operation.load(std::memory_order_relaxed)) / + b.elapse_sec()); + delete db; +} diff --git a/src/main.rs b/src/main.rs index a63bcde..3843bd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,7 +64,7 @@ fn main() { opt.tmp_store = true; // make sure there's no remote indirection opt.max_inline_size = 4096; - opt.cache_capacity = 3 << 30; // this is very important for large key-value store + // opt.cache_capacity = 3 << 30; // this is very important for large key-value store let db = Mace::new(opt.validate().unwrap()).unwrap(); let value = Arc::new(vec![b'0'; args.value_size]); @@ -163,12 +163,10 @@ fn main() { // println!("{:<20} {}", "Test Mode:", args.mode); // println!("{:<20} {}", "Threads:", args.threads); - // println!("{:<20} {total}", "Total Ops:"); - // println!("{:<20} {:.2}s", "Duration:", duration.as_secs_f64()); - // println!("{:<20} {ops:.2}", "OPS:"); + // println!("{:<20} {}", "Iterations", args.iterations); // println!("{:<20} {}B", "Key Size:", args.key_size); // println!("{:<20} {}B", "Value Size:", args.value_size); - + // println!("{:<20} {ops}", "Total Ops:"); // if args.mode == "mixed" { // println!("{:<20} {}%", "Insert Ratio:", args.insert_ratio); // }