From 7578f5d728fc21d5ce11215f2a373fb66549ed7a Mon Sep 17 00:00:00 2001 From: wesley <865373641@qq.com> Date: Fri, 3 Jan 2025 07:00:46 +0800 Subject: [PATCH] test_bench ver1 --- .vscode/settings.json | 73 ++++++++++++++++++ CMakeLists.txt | 7 +- test/test_bench.cc | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d87ba05 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,73 @@ +{ + "files.associations": { + "iostream": "cpp", + "chrono": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "cinttypes": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b56bb39..3b03304 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -545,4 +545,9 @@ target_link_libraries(test_vtable PRIVATE leveldb gtest) add_executable(test_basicio "${PROJECT_SOURCE_DIR}/test/test_basicio.cc" ) -target_link_libraries(test_basicio PRIVATE leveldb gtest) \ No newline at end of file +target_link_libraries(test_basicio PRIVATE leveldb gtest) + +add_executable(test_bench + "${PROJECT_SOURCE_DIR}/test/test_bench.cc" +) +target_link_libraries(test_bench PRIVATE leveldb gtest) \ No newline at end of file diff --git a/test/test_bench.cc b/test/test_bench.cc index e69de29..88c4e89 100644 --- a/test/test_bench.cc +++ b/test/test_bench.cc @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/db.h" + +using namespace leveldb; + +// Number of key/values to operate in database +constexpr int num_ = 100000; +// Size of each value +constexpr int value_size_ = 1000; +// Number of read operations +constexpr int reads_ = 100000; +// Number of findkeysbyfield operations +constexpr int search_ = 50; +Status OpenDB(std::string dbName, DB **db) { + Options options; + options.create_if_missing = true; + return DB::Open(options, dbName, db); +} + +// DB::Put() +void InsertData(DB *db, std::vector &lats) { + WriteOptions writeOptions; + srand(0); + int64_t latency = 0; + auto end_time = std::chrono::steady_clock::now(); + auto last_time = end_time; + + for (int i = 0; i < num_; ++i) { + int key_ = rand() % num_+1; + int value_ = std::rand() % (num_ + 1); + std::string key = std::to_string(key_); + FieldArray field_array = { + {"1", std::to_string(value_)}, + }; + + auto fields = Fields(field_array); + db->Put(writeOptions, key, fields); + + end_time = std::chrono::steady_clock::now(); + latency = std::chrono::duration_cast(end_time - last_time).count(); + last_time = end_time; + lats.emplace_back(latency); + } +} + +// DB::Get() +void GetData(DB *db, std::vector &lats) { + ReadOptions readOptions; + srand(0); + int64_t latency = 0; + auto end_time = std::chrono::steady_clock::now(); + auto last_time = end_time; + for (int i = 0; i < reads_; ++i) { + int key_ = rand() % num_+1; + std::string key = std::to_string(key_); + Fields ret; + db->Get(readOptions, key, &ret); + end_time = std::chrono::steady_clock::now(); + latency = std::chrono::duration_cast(end_time - last_time).count(); + last_time = end_time; + lats.emplace_back(latency); + } + +} + +// DB::Iterator() +void ReadOrdered(DB *db, std::vector &lats) { + Iterator* iter = db->NewIterator(ReadOptions()); + int i = 0; + + int64_t latency = 0; + auto end_time = std::chrono::steady_clock::now(); + auto last_time = end_time; + for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) { + ++i; + end_time = std::chrono::steady_clock::now(); + latency = std::chrono::duration_cast(end_time - last_time).count(); + last_time = end_time; + lats.emplace_back(latency); + } + delete iter; +} + +// DB::FindKeysByField() +void SearchField(DB *db, std::vector &lats) { + int64_t latency = 0; + auto end_time = std::chrono::steady_clock::now(); + auto last_time = end_time; + srand(0); + for (int i = 0; i < search_; ++i) { + int value_ = std::rand() % (num_ + 1); + Field field_to_search = {"1", std::to_string(value_)}; + const std::vector key_ret = db->FindKeysByField(field_to_search); + end_time = std::chrono::steady_clock::now(); + latency = std::chrono::duration_cast(end_time - last_time).count(); + last_time = end_time; + lats.emplace_back(latency); + } +} + +double CalculatePercentile(const std::vector& latencies, double percentile) { + if (latencies.empty()) return 0.0; + + std::vector sorted_latencies = latencies; + std::sort(sorted_latencies.begin(), sorted_latencies.end()); + + size_t index = static_cast(percentile * sorted_latencies.size()); + if (index >= sorted_latencies.size()) index = sorted_latencies.size() - 1; + + return sorted_latencies[index]; +} + +TEST(TestBench, Throughput) { + DB *db; + if(OpenDB("testdb", &db).ok() == false) { + std::cerr << "open db failed" << std::endl; + abort(); + } + + std::vector lats; + + // Put() + auto start_time = std::chrono::steady_clock::now(); + InsertData(db, lats); + auto end_time = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time).count(); + std::cout << "Throughput of Put(): " << num_ / duration << " ops/ms" << std::endl; + // Get() + start_time = std::chrono::steady_clock::now(); + GetData(db, lats); + end_time = std::chrono::steady_clock::now(); + duration = std::chrono::duration_cast(end_time - start_time).count(); + std::cout << "Throughput of Get(): " << reads_ / duration << " ops/ms" << std::endl; + // Iterator() + start_time = std::chrono::steady_clock::now(); + ReadOrdered(db, lats); + end_time = std::chrono::steady_clock::now(); + duration = std::chrono::duration_cast(end_time - start_time).count(); + std::cout << "Throughput of Iterator(): " << reads_ / duration << " ops/ms" << std::endl; + // FindKeysbyField() + start_time = std::chrono::steady_clock::now(); + SearchField(db, lats); + end_time = std::chrono::steady_clock::now(); + duration = std::chrono::duration_cast(end_time - start_time).count(); + std::cout << "Throughput of FindKeysbyField(): " << search_ / duration << " ops/ms" << std::endl; + + delete db; +} + +TEST(TestBench, Latency) { + DB *db; + if(OpenDB("testdb", &db).ok() == false) { + std::cerr << "open db failed" << std::endl; + abort(); + } + + std::vector put_lats; + std::vector get_lats; + std::vector iter_lats; + std::vector search_lats; + auto calc_lat = [](const std::vector& latencies) { + double avg = 0.0; + for (auto latency : latencies) { + avg += latency; + } + avg /= latencies.size(); + + double p75 = CalculatePercentile(latencies, 0.75); + double p99 = CalculatePercentile(latencies, 0.99); + + return std::make_tuple(avg, p75, p99); + }; + + InsertData(db, put_lats); + auto [put_avg, put_p75, put_p99] = calc_lat(put_lats); + std::cout << "Put Latency (avg, P75, P99): " << put_avg << " micros/op, " << put_p75 << " micros/op, " << put_p99 << " micros/op" << std::endl; + + GetData(db, get_lats); + auto [get_avg, get_p75, get_p99] = calc_lat(get_lats); + std::cout << "Get Latency (avg, P75, P99): " << get_avg << " micros/op, " << get_p75 << " micros/op, " << get_p99 << " micros/op" << std::endl; + + ReadOrdered(db, iter_lats); + auto [iter_avg, iter_p75, iter_p99] = calc_lat(iter_lats); + std::cout << "Iterator Latency (avg, P75, P99): " << iter_avg << " micros/op, " << iter_p75 << " micros/op, " << iter_p99 << " micros/op" << std::endl; + + SearchField(db, search_lats); + auto [search_avg, search_p75, search_p99] = calc_lat(search_lats); + std::cout << "FindKeysByField Latency (avg, P75, P99): " << search_avg << " micros/op, " << search_p75 << " micros/op, " << search_p99 << " micros/op" << std::endl; + + delete db; + +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}