GUJIEJASON 8 месяцев назад
Родитель
Сommit
31658444b8
3 измененных файлов: 1243 добавлений и 1 удалений
  1. +7
    -1
      CMakeLists.txt
  2. +1090
    -0
      benchmarks/db_bench_kv.cc
  3. +146
    -0
      test/bench_test.cc

+ 7
- 1
CMakeLists.txt Просмотреть файл

@ -549,4 +549,10 @@ add_executable(kv_test
"${PROJECT_SOURCE_DIR}/test/kv_test.cc"
test/kv_test.cc
)
target_link_libraries(kv_test PRIVATE leveldb gtest)
target_link_libraries(kv_test PRIVATE leveldb gtest)
add_executable(bench_test
"${PROJECT_SOURCE_DIR}/test/bench_test.cc"
test/bench_test.cc
)
target_link_libraries(bench_test PRIVATE leveldb gtest)

+ 1090
- 0
benchmarks/db_bench_kv.cc
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 146
- 0
test/bench_test.cc Просмотреть файл

@ -0,0 +1,146 @@
#include <iostream>
#include <gtest/gtest.h>
#include <chrono>
#include <vector>
#include "leveldb/env.h"
#include "leveldb/db.h"
#include "db/fields.h"
#include "leveldb/write_batch.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;
Status OpenDB(std::string dbName, DB **db) {
Options options;
options.create_if_missing = true;
return DB::Open(options, dbName, db);
}
void InsertData(DB *db, std::vector<int64_t> &lats) {
WriteOptions writeOptions;
srand(0);
for (int i = 0; i < num_; ++i) {
int key_ = rand() % num_ + 1;
std::string key = std::to_string(key_);
std::string value(value_size_, 'a');
auto start_time = std::chrono::steady_clock::now();
db->Put(writeOptions, key, value);
auto end_time = std::chrono::steady_clock::now();
lats.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count());
}
}
void InsertFields(DB *db, std::vector<int64_t> &lats) {
WriteOptions writeOptions;
srand(0);
for (int i = 0; i < num_; ++i) {
int key_ = rand() % num_ + 1;
std::string key = std::to_string(key_);
FieldArray fields = {{"field" + std::to_string(key_), "old_value_" + std::to_string(key)}};
Fields f(fields);
auto start_time = std::chrono::steady_clock::now();
db->PutFields(writeOptions, Slice(key), f);
auto end_time = std::chrono::steady_clock::now();
lats.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count());
}
}
void GetData(DB *db, std::vector<int64_t> &lats) {
ReadOptions readOptions;
srand(0);
for (int i = 0; i < reads_; ++i) {
int key_ = rand() % num_ + 1;
std::string key = std::to_string(key_);
std::string value;
auto start_time = std::chrono::steady_clock::now();
db->Get(readOptions, key, &value);
auto end_time = std::chrono::steady_clock::now();
lats.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count());
}
}
void ReadOrdered(DB *db, std::vector<int64_t> &lats) {
Iterator* iter = db->NewIterator(ReadOptions());
int i = 0;
for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) {
++i;
auto start_time = std::chrono::steady_clock::now();
// Just iterating over the data without performing any operation.
auto end_time = std::chrono::steady_clock::now();
lats.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count());
}
delete iter;
}
void FindKeys(DB *db, std::vector<int64_t> &lats) {
srand(0);
for (int i = 0; i < reads_; ++i) {
int key_ = rand() % num_ + 1;
FieldArray fields_to_find = {{"field" + std::to_string(key_), "old_value_" + std::to_string(key_)}};
auto start_time = std::chrono::steady_clock::now();
Fields::FindKeysByFields(db, fields_to_find);
auto end_time = std::chrono::steady_clock::now();
lats.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count());
}
}
double CalculatePercentile(const std::vector<int64_t>& latencies, double percentile) {
if (latencies.empty()) return 0.0;
std::vector<int64_t> sorted_latencies = latencies;
std::sort(sorted_latencies.begin(), sorted_latencies.end());
size_t index = static_cast<size_t>(percentile * sorted_latencies.size());
if (index >= sorted_latencies.size()) index = sorted_latencies.size() - 1;
return sorted_latencies[index];
}
template<typename Func>
void RunBenchmark(const char* name, Func func) {
DB *db;
if (!OpenDB("testdb_bench", &db).ok()) {
std::cerr << "open db failed" << std::endl;
abort();
}
std::vector<int64_t> lats;
auto start_time = std::chrono::steady_clock::now();
func(db, lats);
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
double avg = 0.0;
for (auto latency : lats) {
avg += latency;
}
avg /= lats.size();
double p75 = CalculatePercentile(lats, 0.75);
double p99 = CalculatePercentile(lats, 0.99);
std::cout << name << " Latency (avg, P75, P99): " << avg << " micros/op, " << p75 << " micros/op, " << p99 << " micros/op" << std::endl;
std::cout << name << " Throughput: " << lats.size() / duration << " ops/ms" << std::endl;
delete db;
}
class BenchTest : public ::testing::TestWithParam<double> {};
TEST_P(BenchTest, PutLatency) { RunBenchmark("Put", InsertData); }
TEST_P(BenchTest, PutLatency) { RunBenchmark("PutFields", InsertFields); }
TEST_P(BenchTest, GetLatency) { RunBenchmark("Get", GetData); }
TEST_P(BenchTest, IteratorLatency) { RunBenchmark("Iterator", ReadOrdered); }
TEST_P(BenchTest, FindKeysByFieldLatency) { RunBenchmark("FindKeysByFields", FindKeys); }
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Загрузка…
Отмена
Сохранить