src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 / 389
0.0%
Branches:
0 / 1158
0.0%
Functions:
0 / 25
0.0%

storage/kv_engine/benchmark_kv_engine.cc
Line Branch Exec Source
1 #include <unistd.h>
2
3 #include <algorithm>
4 #include <atomic>
5 #include <chrono>
6 #include <cmath>
7 #include <cstdint>
8 #include <cstdio>
9 #include <memory>
10 #include <mutex>
11 #include <numeric>
12 #include <stdexcept>
13 #include <string>
14 #include <string_view>
15 #include <thread>
16 #include <vector>
17
18 #include "base/bind_core.h"
19 #include "base/factory.h"
20 #include "base/init.h"
21 #include "base/log.h"
22 #include "memory/shm_file.h"
23 #include "storage/io_backend/force_link.h"
24 #include "storage/kv_engine/base_kv.h"
25 #include "storage/kv_engine/engine_selector.h"
26 #include "storage/ssd_layout/ssd_layout.h"
27
28 DEFINE_string(
29 dram_path,
30 "",
31 "DRAM data directory; empty only works with anonymous DRAM allocators");
32 DEFINE_string(ssd_path, "", "SSD data directory");
33 DEFINE_string(index_type, "DRAM_EXTENDIBLE_HASH", "index.type");
34 DEFINE_string(value_store_type, "DRAM_VALUE_STORE", "value.type");
35 DEFINE_string(engine_class, "KVEngineComposite", "BaseKV factory class name");
36 DEFINE_string(fasterkv_storage,
37 "memory",
38 "KVEngineFasterKV storage backend: memory|ssd");
39 DEFINE_string(
40 fasterkv_log_path,
41 "",
42 "KVEngineFasterKV SSD log directory; defaults to ssd_path/fasterkv-log");
43 DEFINE_int64(
44 fasterkv_hlog_memory_bytes,
45 0,
46 "KVEngineFasterKV hybrid log memory bytes; 0 uses backend default");
47 DEFINE_double(
48 fasterkv_mutable_fraction,
49 0.0,
50 "KVEngineFasterKV hybrid log mutable fraction; 0 uses backend default");
51 DEFINE_int64(fasterkv_read_cache_bytes,
52 0,
53 "KVEngineFasterKV read cache bytes; 0 disables read cache");
54 DEFINE_string(dram_allocator,
55 "CONCURRENT_SLAB_MEMORY_POOL",
56 "value.dram_allocator.type");
57 DEFINE_string(ssd_io_backend, "IOURING", "SSD IO backend");
58 DEFINE_int32(ssd_queue_depth, 512, "SSD IO queue depth");
59 DEFINE_int64(dram_capacity_bytes, 0, "override DRAM allocator capacity bytes");
60 DEFINE_int64(ssd_capacity_bytes, 0, "override SSD allocator capacity bytes");
61
62 DEFINE_int64(record_count, 100000000, "YCSB record count");
63 DEFINE_string(workload,
64 "c",
65 "YCSB workload: a/b/c or workloada/workloadb/workloadc");
66 DEFINE_string(distribution, "uniform", "key distribution: uniform/zipfian");
67 DEFINE_double(zipfian_alpha, 0.9, "Zipfian alpha");
68 DEFINE_bool(
69 zipfian_scramble,
70 false,
71 "permute the zipfian rank->key mapping so hot ranks are not low key "
72 "ids; used to test frequency-aware placement without the "
73 "sequential-load bias");
74 DEFINE_string(read_mode, "exists", "read mode: exists/get/batch_get_flat");
75 DEFINE_int32(batch_keys, 500, "keys per BatchGetFlat operation");
76 DEFINE_bool(load, true, "run load phase");
77 DEFINE_bool(run, true, "run transaction phase");
78 DEFINE_bool(print_util, false, "print KVEngine utilization after load");
79
80 DEFINE_int32(thread_num, 16, "worker thread count");
81 DEFINE_int32(load_thread_num, 0, "load thread count; 0 uses thread_num");
82 DEFINE_int32(value_size, 128, "value size bytes");
83 DEFINE_int32(running_seconds, 5, "transaction runtime seconds");
84 DEFINE_string(ssd_layout_strategy, "", "plain, bandana, or maxembed");
85 DEFINE_string(ssd_layout_mapping, "", "precomputed SSD layout artifact");
86 DEFINE_string(ssd_layout_query, "", "text query log replayed after load");
87
88 namespace {
89
90 struct PhaseStats {
91 uint64_t total_ops = 0;
92 uint64_t read_ops = 0;
93 uint64_t update_ops = 0;
94 };
95
96 struct WorkloadMix {
97 int read_percent = 100;
98 };
99
100 class FastRandom {
101 public:
102 ✗ explicit FastRandom(uint64_t seed)
103
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ : state_(seed ? seed : 0x9e3779b97f4a7c15ULL) {}
104
105 ✗ uint64_t Next() {
106 ✗ uint64_t x = state_;
107 ✗ x ^= x >> 12;
108 ✗ x ^= x << 25;
109 ✗ x ^= x >> 27;
110 ✗ state_ = x;
111 ✗ return x * 2685821657736338717ULL;
112 }
113
114 ✗ double Uniform01() { return (Next() >> 11) * (1.0 / 9007199254740992.0); }
115
116
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ uint64_t Uniform(uint64_t n) { return n == 0 ? 0 : Next() % n; }
117
118 private:
119 uint64_t state_;
120 };
121
122 class KeyGenerator {
123 public:
124 ✗ KeyGenerator(std::string distribution,
125 uint64_t record_count,
126 double zipfian_alpha,
127 uint64_t seed,
128 bool scramble = false)
129 ✗ : distribution_(std::move(distribution)),
130 ✗ record_count_(record_count),
131 ✗ alpha_(zipfian_alpha),
132 ✗ rng_(seed) {
133
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (record_count_ == 0) {
134
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("record_count must be positive");
135 }
136
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (distribution_ == "zipfian") {
137
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (alpha_ < 0.0) {
138
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("zipfian_alpha must be non-negative");
139 }
140
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (std::abs(alpha_ - 1.0) < 1e-9) {
141 ✗ log_n_ = std::log(static_cast<double>(record_count_));
142 } else {
143 ✗ pow_n_ = std::pow(static_cast<double>(record_count_), 1.0 - alpha_);
144 }
145
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (scramble) {
146 ✗ scramble_stride_ = ChooseCoprimeStride(record_count_);
147 }
148
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ } else if (distribution_ != "uniform") {
149
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("distribution must be uniform or zipfian");
150 }
151 ✗ }
152
153 ✗ uint64_t NextKey() {
154
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (distribution_ == "uniform") {
155 ✗ return rng_.Uniform(record_count_);
156 }
157 ✗ return NextZipfian();
158 }
159
160 ✗ uint64_t NextUint(uint64_t n) { return rng_.Uniform(n); }
161
162 private:
163 ✗ uint64_t NextZipfian() {
164 ✗ const double u = std::max(rng_.Uniform01(), 1e-12);
165 ✗ double rank = 1.0;
166
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (std::abs(alpha_ - 1.0) < 1e-9) {
167 ✗ rank = std::exp(u * log_n_);
168 } else {
169 ✗ rank = std::pow(1.0 + u * (pow_n_ - 1.0), 1.0 / (1.0 - alpha_));
170 }
171 ✗ uint64_t key = static_cast<uint64_t>(rank);
172
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (key >= record_count_) {
173 ✗ key = record_count_ - 1;
174 }
175
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (scramble_stride_ != 0) {
176 ✗ key = (key * scramble_stride_) % record_count_;
177 }
178 ✗ return key;
179 }
180
181 ✗ static uint64_t ChooseCoprimeStride(uint64_t n) {
182 static constexpr uint64_t kPreferredStrides[] = {
183 104729, 99991, 65537, 10007, 97};
184
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (uint64_t candidate : kPreferredStrides) {
185
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ if (candidate < n && std::gcd(candidate, n) == 1) {
186 ✗ return candidate;
187 }
188 }
189
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (uint64_t candidate = n / 2 + 1; candidate > 1; --candidate) {
190
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (std::gcd(candidate, n) == 1) {
191 ✗ return candidate;
192 }
193 }
194 ✗ return 0;
195 }
196
197 std::string distribution_;
198 uint64_t record_count_;
199 double alpha_;
200 double pow_n_ = 1.0;
201 double log_n_ = 0.0;
202 uint64_t scramble_stride_ = 0;
203 FastRandom rng_;
204 };
205
206 ✗ std::string NormalizeWorkload(std::string workload) {
207 ✗ std::transform(workload.begin(), workload.end(), workload.begin(), ::tolower);
208
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "workloada")
209
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return "a";
210
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "workloadb")
211
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return "b";
212
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "workloadc")
213
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return "c";
214 ✗ return workload;
215 }
216
217 ✗ WorkloadMix GetWorkloadMix(const std::string& workload) {
218
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "a")
219 ✗ return WorkloadMix{50};
220
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "b")
221 ✗ return WorkloadMix{95};
222
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (workload == "c")
223 ✗ return WorkloadMix{100};
224
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::invalid_argument(
225 ✗ "workload must be a/b/c or workloada/workloadb/workloadc");
226 }
227
228 ✗ bool IsSsdIndexType(const std::string& type) {
229
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ return type == "SSD" || type == "SSD_EXTENDIBLE_HASH";
230 }
231
232 ✗ bool HasDramValueStore(const std::string& type) {
233
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ return type == "DRAM_VALUE_STORE" || type == "TIERED_VALUE_STORE";
234 }
235
236 ✗ bool HasSsdValueStore(const std::string& type) {
237
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ return type == "SSD_VALUE_STORE" || type == "SSD_STATIC_LAYOUT_VALUE_STORE" ||
238 ✗ type == "TIERED_VALUE_STORE";
239 }
240
241 ✗ bool IsDirectExternalEngine(const std::string& engine_class) {
242
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ return engine_class == "KVEngineFasterKV" ||
243
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ engine_class == "KVEngineHPSHashMap" ||
244 ✗ engine_class == "KVEngineHPSRocksDB";
245 }
246
247 ✗ bool IsLegacyDirectEngine(const std::string& engine_class) {
248
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ return IsDirectExternalEngine(engine_class) ||
249 ✗ engine_class == "KVEnginePetKV";
250 }
251
252 ✗ BaseKVConfig BuildConfig() {
253 ✗ BaseKVConfig config;
254 ✗ const uint64_t capacity = static_cast<uint64_t>(FLAGS_record_count);
255 const uint64_t value_slot_bytes =
256 ✗ static_cast<uint64_t>(std::max(FLAGS_value_size, 1)) + sizeof(uint64_t);
257 ✗ const uint64_t value_capacity = capacity * value_slot_bytes * 1.2;
258 ✗ constexpr uint64_t kMinSsdCapacityBytes = 256ULL * 1024ULL * 1024ULL;
259
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_engine_class == "KVEngineFasterKV") {
260
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ if (FLAGS_fasterkv_storage != "memory" && FLAGS_fasterkv_storage != "ssd") {
261
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("fasterkv_storage must be memory or ssd");
262 }
263
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_fasterkv_mutable_fraction < 0.0 ||
264
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ FLAGS_fasterkv_mutable_fraction > 1.0) {
265
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::invalid_argument(
266 ✗ "fasterkv_mutable_fraction must be in [0, 1]");
267 }
268 config.json_config_ = {
269 {"engine_type", "KVEngineFasterKV"},
270 {"capacity", capacity},
271 ✗ {"path", FLAGS_ssd_path.empty() ? FLAGS_dram_path : FLAGS_ssd_path},
272 {"value_size", FLAGS_value_size},
273
0/68
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ {"fasterkv", {{"storage", FLAGS_fasterkv_storage}}}};
274
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_fasterkv_storage == "ssd") {
275 const std::string log_path =
276 ✗ FLAGS_fasterkv_log_path.empty()
277 ? FLAGS_ssd_path + "/fasterkv-log"
278
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ : FLAGS_fasterkv_log_path;
279
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ config.json_config_["fasterkv"]["log_path"] = log_path;
280 ✗ }
281
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_fasterkv_hlog_memory_bytes > 0) {
282
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["fasterkv"]["hlog_memory_bytes"] =
283 ✗ static_cast<uint64_t>(FLAGS_fasterkv_hlog_memory_bytes);
284 }
285
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_fasterkv_mutable_fraction > 0.0) {
286
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["fasterkv"]["mutable_fraction"] =
287 ✗ FLAGS_fasterkv_mutable_fraction;
288 }
289
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_fasterkv_read_cache_bytes > 0) {
290
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["fasterkv"]["read_cache_bytes"] =
291 ✗ static_cast<uint64_t>(FLAGS_fasterkv_read_cache_bytes);
292 }
293 ✗ config.num_threads_ = std::max(FLAGS_thread_num, FLAGS_load_thread_num);
294 ✗ return config;
295
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ } else if (FLAGS_engine_class == "KVEngineHPSHashMap" ||
296 ✗ FLAGS_engine_class == "KVEngineHPSRocksDB") {
297 const std::string data_path =
298
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ FLAGS_ssd_path.empty() ? FLAGS_dram_path : FLAGS_ssd_path;
299
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (data_path.empty()) {
300
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::invalid_argument(
301
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ "dram_path or ssd_path must be set for " + FLAGS_engine_class);
302 }
303 config.json_config_ = {
304 {"engine_type", FLAGS_engine_class},
305 {"capacity", capacity},
306 {"path", data_path},
307
0/42
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ {"value_size", FLAGS_value_size}};
308 ✗ config.num_threads_ = std::max(FLAGS_thread_num, FLAGS_load_thread_num);
309 ✗ return config;
310
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ } else if (FLAGS_engine_class == "KVEnginePetKV") {
311
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_dram_path.empty()) {
312
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("dram_path must be set for KVEnginePetKV");
313 }
314 config.json_config_ = {
315 {"capacity", capacity},
316 {"path", FLAGS_dram_path},
317 {"value_size", FLAGS_value_size},
318
0/40
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ {"value_capacity", value_capacity}};
319 ✗ config.num_threads_ = std::max(FLAGS_thread_num, FLAGS_load_thread_num);
320 ✗ return config;
321 }
322
323
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const bool ssd_index = IsSsdIndexType(FLAGS_index_type);
324
325 config.json_config_ = {
326 {"engine_type", "KVEngineComposite"},
327 {"capacity", capacity},
328 {"index", {{"type", FLAGS_index_type}}},
329 {"value",
330 {{"type", FLAGS_value_store_type},
331
0/80
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ {"default_value_size_hint", FLAGS_value_size}}}};
332
333
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (ssd_index) {
334
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ config.json_config_["index"]["path"] = FLAGS_ssd_path + "/index.db";
335
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["index"]["io"] = {
336 {"type", FLAGS_ssd_io_backend},
337 {"queue_depth", FLAGS_ssd_queue_depth},
338
0/32
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ {"base_offset_bytes", 0}};
339 }
340
341 ✗ uint64_t dram_capacity =
342 ✗ FLAGS_dram_capacity_bytes > 0
343
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ ? static_cast<uint64_t>(FLAGS_dram_capacity_bytes)
344 : value_capacity;
345 const uint64_t ssd_capacity =
346 ✗ FLAGS_ssd_capacity_bytes > 0
347
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ ? static_cast<uint64_t>(FLAGS_ssd_capacity_bytes)
348 ✗ : std::max(value_capacity, kMinSsdCapacityBytes);
349
350
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_value_store_type == "DRAM_VALUE_STORE") {
351
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!FLAGS_dram_path.empty()) {
352
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ config.json_config_["value"]["path"] = FLAGS_dram_path + "/value";
353 }
354
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["dram_allocator"] = {
355
0/24
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ {"type", FLAGS_dram_allocator}, {"capacity_bytes", dram_capacity}};
356 // TODO(xieminhui): fix BUG when R2_ALLOC is used, dram_capacity is not
357 // enough, should be 10 times of value_capacity
358
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_dram_allocator == "R2_ALLOC")
359 ✗ dram_capacity *= 10;
360
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ } else if (FLAGS_value_store_type == "SSD_VALUE_STORE") {
361
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ config.json_config_["value"]["path"] = FLAGS_ssd_path + "/value.db";
362
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["ssd_allocator"] = {
363 {"type", "SSD_SLAB"},
364 {"capacity_bytes", ssd_capacity},
365 ✗ {"min_block_size", 128},
366 ✗ {"max_block_size", 4096},
367 {"io",
368 {{"type", FLAGS_ssd_io_backend},
369 {"queue_depth", FLAGS_ssd_queue_depth},
370
0/80
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ {"base_offset_bytes", 4096}}}};
371
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ } else if (FLAGS_value_store_type == "TIERED_VALUE_STORE") {
372 ✗ constexpr double dram_ratio = 0.1;
373 ✗ dram_capacity = dram_capacity * dram_ratio;
374
375
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["dram_allocator"] = {
376 {"type", FLAGS_dram_allocator},
377 {"capacity_bytes", dram_capacity},
378
0/36
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ {"path", FLAGS_dram_path + "/dram"}};
379
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["ssd_allocator"] = {
380 {"type", "SSD_SLAB"},
381 {"capacity_bytes", ssd_capacity},
382 ✗ {"min_block_size", 128},
383 ✗ {"max_block_size", 4096},
384
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ {"path", FLAGS_ssd_path + "/ssd.db"},
385 {"io",
386 {{"type", FLAGS_ssd_io_backend},
387 {"queue_depth", FLAGS_ssd_queue_depth},
388
0/90
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ {"base_offset_bytes", 4096}}}};
389
0/20
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ config.json_config_["value"]["tiering"] = {{"cache_policy", "LRU"}};
390 }
391
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ if (!FLAGS_ssd_layout_strategy.empty() &&
392 ✗ FLAGS_ssd_layout_strategy != "plain") {
393
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_ssd_layout_mapping.empty()) {
394
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("ssd_layout_mapping is required");
395 }
396
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_value_store_type != "TIERED_VALUE_STORE") {
397
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ config.json_config_["value"]["type"] = "SSD_STATIC_LAYOUT_VALUE_STORE";
398
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ config.json_config_["value"]["path"] = FLAGS_ssd_path + "/value.db";
399
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["io"] = {
400 {"type", FLAGS_ssd_io_backend},
401 {"queue_depth", FLAGS_ssd_queue_depth},
402
0/32
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ {"base_offset_bytes", 0}};
403 }
404
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ config.json_config_["value"]["ssd_layout"] = {
405 {"strategy", FLAGS_ssd_layout_strategy},
406
0/26
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ {"mapping_path", FLAGS_ssd_layout_mapping}};
407 }
408
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ LOG(INFO) << config.json_config_.dump(2);
409 ✗ config.num_threads_ = std::max(FLAGS_thread_num, FLAGS_load_thread_num);
410 ✗ return config;
411 ✗ }
412
413 ✗ PhaseStats LoadRecords(BaseKV* kv, int load_threads, uint64_t record_count) {
414 ✗ std::vector<std::thread> threads;
415
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::vector<uint64_t> counts(load_threads, 0);
416 ✗ const uint64_t per_thread = (record_count + load_threads - 1) / load_threads;
417
418
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int tid = 0; tid < load_threads; ++tid) {
419
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ threads.emplace_back([kv, tid, per_thread, record_count, &counts]() {
420
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ base::auto_bind_core();
421
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::string value(FLAGS_value_size, static_cast<char>('a' + (tid % 26)));
422 ✗ const uint64_t begin = static_cast<uint64_t>(tid) * per_thread;
423 ✗ const uint64_t end = std::min(record_count, begin + per_thread);
424
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (uint64_t key = begin; key < end; ++key) {
425
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ kv->Put(key, std::string_view(value.data(), value.size()), tid);
426 ✗ ++counts[tid];
427 }
428 ✗ });
429 }
430
0/2
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ for (auto& thread : threads) {
431
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ thread.join();
432 }
433
434 ✗ PhaseStats stats;
435
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ for (uint64_t count : counts) {
436 ✗ stats.total_ops += count;
437 ✗ stats.update_ops += count;
438 }
439 ✗ return stats;
440 ✗ }
441
442 ✗ PhaseStats RunTransactions(
443 BaseKV* kv,
444 const std::string& workload,
445 const std::string& distribution,
446 int threads_num,
447 uint64_t record_count,
448 int seconds) {
449
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const WorkloadMix mix = GetWorkloadMix(workload);
450 ✗ const bool use_exists = FLAGS_read_mode == "exists";
451 ✗ const bool use_batch_get_flat = FLAGS_read_mode == "batch_get_flat";
452
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ if (!use_exists && FLAGS_read_mode != "get" && !use_batch_get_flat) {
453
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::invalid_argument(
454 ✗ "read_mode must be exists, get, or batch_get_flat");
455 }
456
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_batch_keys <= 0) {
457
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ throw std::invalid_argument("batch_keys must be positive");
458 }
459
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ if (use_batch_get_flat && FLAGS_value_size % sizeof(float) != 0) {
460
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::invalid_argument(
461 ✗ "batch_get_flat requires value_size to be a multiple of sizeof(float)");
462 }
463 ✗ const int embedding_dim = FLAGS_value_size / sizeof(float);
464
465 ✗ std::atomic<bool> start{false};
466 ✗ std::atomic<bool> stop{false};
467 ✗ std::vector<std::thread> threads;
468
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::vector<PhaseStats> stats(threads_num);
469 ✗ std::exception_ptr first_exception;
470 ✗ std::mutex exception_mu;
471
472
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int tid = 0; tid < threads_num; ++tid) {
473
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ threads.emplace_back([&, tid]() {
474 try {
475
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ base::auto_bind_core();
476 KeyGenerator key_gen(
477 ✗ distribution,
478 ✗ record_count,
479 FLAGS_zipfian_alpha,
480 ✗ 0x9e3779b97f4a7c15ULL + static_cast<uint64_t>(tid),
481
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ FLAGS_zipfian_scramble);
482 std::string value(
483
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ FLAGS_value_size, static_cast<char>('A' + (tid % 26)));
484 ✗ std::string read_value;
485
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::vector<uint64_t> batch_keys(static_cast<size_t>(FLAGS_batch_keys));
486 ✗ std::vector<float> flat_values(static_cast<size_t>(FLAGS_batch_keys) *
487
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ static_cast<size_t>(embedding_dim));
488 ✗ PhaseStats local;
489
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ while (!start.load(std::memory_order_acquire)) {
490 }
491
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ while (!stop.load(std::memory_order_relaxed)) {
492 const bool do_read =
493 ✗ static_cast<int>(key_gen.NextUint(100)) < mix.read_percent;
494
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (do_read) {
495
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (use_batch_get_flat) {
496
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int i = 0; i < FLAGS_batch_keys; ++i) {
497
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ batch_keys[static_cast<size_t>(i)] = key_gen.NextKey();
498 }
499
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ const bool ok = kv->BatchGetFlat(
500 base::ConstArray<uint64_t>(
501 ✗ batch_keys.data(), batch_keys.size()),
502 flat_values.data(),
503 FLAGS_batch_keys,
504 ✗ embedding_dim,
505 tid);
506
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (!ok) {
507
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ throw std::runtime_error(
508 "read_mode=batch_get_flat is unsupported by this KV "
509 ✗ "engine");
510 }
511 ✗ local.read_ops += static_cast<uint64_t>(FLAGS_batch_keys);
512 ✗ local.total_ops += static_cast<uint64_t>(FLAGS_batch_keys);
513 ✗ continue;
514 ✗ }
515
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const uint64_t key = key_gen.NextKey();
516
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (use_exists) {
517
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ (void)kv->Exists(key, tid);
518 } else {
519
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kv->Get(key, read_value, tid);
520 }
521 ✗ ++local.read_ops;
522 } else {
523
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const uint64_t key = key_gen.NextKey();
524
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ kv->Put(key, std::string_view(value.data(), value.size()), tid);
525 ✗ ++local.update_ops;
526 }
527 ✗ ++local.total_ops;
528 }
529 ✗ stats[tid] = local;
530 ✗ } catch (...) {
531 {
532
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ std::lock_guard<std::mutex> lock(exception_mu);
533
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!first_exception) {
534 ✗ first_exception = std::current_exception();
535 }
536 ✗ }
537 ✗ stop.store(true, std::memory_order_relaxed);
538 ✗ }
539 ✗ });
540 }
541
542 ✗ start.store(true, std::memory_order_release);
543
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ sleep(seconds);
544 ✗ stop.store(true, std::memory_order_relaxed);
545
0/2
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ for (auto& thread : threads) {
546
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ thread.join();
547 }
548
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (first_exception) {
549 ✗ std::rethrow_exception(first_exception);
550 }
551
552 ✗ PhaseStats total;
553
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ for (const auto& each : stats) {
554 ✗ total.total_ops += each.total_ops;
555 ✗ total.read_ops += each.read_ops;
556 ✗ total.update_ops += each.update_ops;
557 }
558 ✗ return total;
559 ✗ }
560
561 ✗ double SecondsSince(std::chrono::steady_clock::time_point start,
562 std::chrono::steady_clock::time_point end) {
563
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return std::chrono::duration_cast<std::chrono::duration<double>>(end - start)
564 ✗ .count();
565 }
566
567 ✗ void ReplayQueryLog(BaseKV* kv) {
568
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_ssd_layout_query.empty()) {
569 ✗ return;
570 }
571
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const auto graph = ssd_layout::ReadQueryLog(FLAGS_ssd_layout_query, false);
572 ✗ uint64_t queries = 0;
573 ✗ uint64_t rows = 0;
574
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kv->ResetStats();
575 ✗ const auto begin = std::chrono::steady_clock::now();
576
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ for (size_t query = 0; query + 1 < graph.xpins.size(); ++query) {
577 ✗ std::vector<uint64_t> keys;
578
0/2
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ keys.reserve(graph.xpins[query + 1] - graph.xpins[query]);
579
0/2
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ keys.insert(keys.end(),
580 ✗ graph.pins.begin() + graph.xpins[query],
581 ✗ graph.pins.begin() + graph.xpins[query + 1]);
582
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (keys.empty()) {
583 ✗ continue;
584 }
585 ✗ std::vector<base::ConstArray<float>> values;
586
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ kv->BatchGet(base::ConstArray<uint64_t>(keys), &values, 0);
587 ✗ ++queries;
588 ✗ rows += keys.size();
589
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ }
590
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ const double seconds = SecondsSince(begin, std::chrono::steady_clock::now());
591
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::printf("LAYOUT_RESULT queries=%lu rows=%lu seconds=%.6f%s\n",
592 queries,
593 rows,
594 seconds,
595
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kv->ExtraResultFields().c_str());
596 ✗ }
597
598 } // namespace
599
600 ✗ int RunBenchmark(int argc, char* argv[]) {
601
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ ForceLinkIOBackends();
602
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ base::Init(&argc, &argv);
603
604
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_record_count <= 0) {
605
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "record_count must be positive";
606 }
607
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_thread_num <= 0) {
608
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "thread_num must be positive";
609 }
610
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_value_size <= 0) {
611
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "value_size must be positive";
612 }
613
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_running_seconds <= 0) {
614
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "running_seconds must be positive";
615 }
616
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!IsLegacyDirectEngine(FLAGS_engine_class) &&
617
0/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ IsSsdIndexType(FLAGS_index_type) && FLAGS_ssd_path.empty()) {
618
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "ssd_path must be set for SSD index";
619 }
620
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!IsLegacyDirectEngine(FLAGS_engine_class) &&
621
0/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ HasSsdValueStore(FLAGS_value_store_type) && FLAGS_ssd_path.empty()) {
622
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "ssd_path must be set for SSD/TIERED value store";
623 }
624
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!IsLegacyDirectEngine(FLAGS_engine_class) &&
625
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ !FLAGS_ssd_layout_strategy.empty() &&
626
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ FLAGS_ssd_layout_strategy != "plain" && FLAGS_ssd_path.empty()) {
627
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "ssd_path must be set for a static SSD layout";
628 }
629
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ if (!IsLegacyDirectEngine(FLAGS_engine_class) &&
630
0/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ FLAGS_value_store_type == "TIERED_VALUE_STORE" &&
631 ✗ FLAGS_dram_path.empty()) {
632
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "dram_path must be set for TIERED value store";
633 }
634
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_engine_class == "KVEngineFasterKV" &&
635
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ FLAGS_fasterkv_storage == "ssd" && FLAGS_ssd_path.empty() &&
636 ✗ FLAGS_fasterkv_log_path.empty()) {
637
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ LOG(FATAL) << "ssd_path or fasterkv_log_path must be set for "
638
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ "KVEngineFasterKV fasterkv_storage=ssd";
639 }
640
641
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ const std::string workload = NormalizeWorkload(FLAGS_workload);
642
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ (void)GetWorkloadMix(workload);
643 ✗ const int load_threads =
644
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ FLAGS_load_thread_num > 0 ? FLAGS_load_thread_num : FLAGS_thread_num;
645
646 ✗ base::PMMmapRegisterCenter::GetConfig().backend =
647 ✗ base::PMMmapRegisterCenter::BackendFromUseDram(
648
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ HasDramValueStore(FLAGS_value_store_type) ||
649
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ IsLegacyDirectEngine(FLAGS_engine_class));
650
651
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ BaseKVConfig config = BuildConfig();
652 ✗ std::unique_ptr<BaseKV> kv;
653
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (FLAGS_engine_class == "KVEngine") {
654
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ auto resolved = base::ResolveEngine(config);
655
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kv.reset(base::Factory<BaseKV, const BaseKVConfig&>::NewInstance(
656 resolved.engine, resolved.cfg));
657 ✗ } else {
658
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kv.reset(base::Factory<BaseKV, const BaseKVConfig&>::NewInstance(
659 FLAGS_engine_class, config));
660 }
661
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!kv) {
662
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(FATAL) << "failed to create KVEngine";
663 }
664
665
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_load) {
666 ✗ const auto begin = std::chrono::steady_clock::now();
667
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ PhaseStats load_stats = LoadRecords(
668 kv.get(), load_threads, static_cast<uint64_t>(FLAGS_record_count));
669 ✗ const auto end = std::chrono::steady_clock::now();
670
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const double seconds = SecondsSince(begin, end);
671 ✗ const double throughput =
672
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ seconds > 0.0 ? static_cast<double>(load_stats.total_ops) / seconds
673 : 0.0;
674
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ std::printf(
675 "YCSB_LOAD_RESULT records=%ld threads=%d seconds=%.6f ops=%lu "
676 "throughput_ops_sec=%.6f\n",
677 FLAGS_record_count,
678 load_threads,
679 seconds,
680 load_stats.total_ops,
681 throughput);
682
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_print_util) {
683
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ kv->Util();
684 }
685 }
686
687
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (FLAGS_run) {
688 ✗ const auto begin = std::chrono::steady_clock::now();
689
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ PhaseStats run_stats = RunTransactions(
690 kv.get(),
691 workload,
692 FLAGS_distribution,
693 FLAGS_thread_num,
694 static_cast<uint64_t>(FLAGS_record_count),
695 FLAGS_running_seconds);
696 ✗ const auto end = std::chrono::steady_clock::now();
697
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ const double seconds = SecondsSince(begin, end);
698 ✗ const double throughput =
699
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ seconds > 0.0 ? static_cast<double>(run_stats.total_ops) / seconds
700 : 0.0;
701
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ std::printf(
702 "YCSB_RESULT workload=%s distribution=%s zipfian_alpha=%.6f "
703 "read_mode=%s threads=%d records=%ld runtime_s=%.6f ops=%lu "
704 "throughput_ops_sec=%.6f read_ops=%lu update_ops=%lu\n",
705 workload.c_str(),
706 FLAGS_distribution.c_str(),
707 FLAGS_zipfian_alpha,
708 FLAGS_read_mode.c_str(),
709 FLAGS_thread_num,
710 FLAGS_record_count,
711 seconds,
712 run_stats.total_ops,
713 throughput,
714 run_stats.read_ops,
715 run_stats.update_ops);
716 }
717
718
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ ReplayQueryLog(kv.get());
719
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(INFO) << "gracefully exit";
720 ✗ return 0;
721 ✗ }
722
723 ✗ int main(int argc, char* argv[]) {
724 try {
725
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ return RunBenchmark(argc, argv);
726
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ } catch (const std::exception& e) {
727
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ std::fprintf(stderr, "ERROR benchmark_kv_engine: %s\n", e.what());
728 ✗ return 1;
729 ✗ }
730 }
731