1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 #ifndef ROCKSDB_LITE
11 #ifndef GFLAGS
12 #include <cstdio>
main()13 int main() {
14 fprintf(stderr, "Please install gflags to run trace_analyzer test\n");
15 return 1;
16 }
17 #else
18
19 #include <chrono>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <sstream>
23 #include <thread>
24
25 #include "db/db_test_util.h"
26 #include "file/read_write_util.h"
27 #include "rocksdb/db.h"
28 #include "rocksdb/env.h"
29 #include "rocksdb/status.h"
30 #include "rocksdb/trace_reader_writer.h"
31 #include "test_util/testharness.h"
32 #include "test_util/testutil.h"
33 #include "tools/trace_analyzer_tool.h"
34 #include "trace_replay/trace_replay.h"
35
36 namespace ROCKSDB_NAMESPACE {
37
38 namespace {
39 static const int kMaxArgCount = 100;
40 static const size_t kArgBufferSize = 100000;
41 } // namespace
42
43 // The helper functions for the test
44 class TraceAnalyzerTest : public testing::Test {
45 public:
TraceAnalyzerTest()46 TraceAnalyzerTest() : rnd_(0xFB) {
47 // test_path_ = test::TmpDir() + "trace_analyzer_test";
48 test_path_ = test::PerThreadDBPath("trace_analyzer_test");
49 env_ = ROCKSDB_NAMESPACE::Env::Default();
50 env_->CreateDir(test_path_);
51 dbname_ = test_path_ + "/db";
52 }
53
~TraceAnalyzerTest()54 ~TraceAnalyzerTest() override {}
55
GenerateTrace(std::string trace_path)56 void GenerateTrace(std::string trace_path) {
57 Options options;
58 options.create_if_missing = true;
59 options.merge_operator = MergeOperators::CreatePutOperator();
60 ReadOptions ro;
61 WriteOptions wo;
62 TraceOptions trace_opt;
63 DB* db_ = nullptr;
64 std::string value;
65 std::unique_ptr<TraceWriter> trace_writer;
66 Iterator* single_iter = nullptr;
67
68 ASSERT_OK(
69 NewFileTraceWriter(env_, env_options_, trace_path, &trace_writer));
70 ASSERT_OK(DB::Open(options, dbname_, &db_));
71 ASSERT_OK(db_->StartTrace(trace_opt, std::move(trace_writer)));
72
73 WriteBatch batch;
74 ASSERT_OK(batch.Put("a", "aaaaaaaaa"));
75 ASSERT_OK(batch.Merge("b", "aaaaaaaaaaaaaaaaaaaa"));
76 ASSERT_OK(batch.Delete("c"));
77 ASSERT_OK(batch.SingleDelete("d"));
78 ASSERT_OK(batch.DeleteRange("e", "f"));
79 ASSERT_OK(db_->Write(wo, &batch));
80
81 ASSERT_OK(db_->Get(ro, "a", &value));
82 single_iter = db_->NewIterator(ro);
83 single_iter->Seek("a");
84 single_iter->SeekForPrev("b");
85 delete single_iter;
86 std::this_thread::sleep_for (std::chrono::seconds(1));
87
88 db_->Get(ro, "g", &value);
89
90 ASSERT_OK(db_->EndTrace());
91
92 ASSERT_OK(env_->FileExists(trace_path));
93
94 std::unique_ptr<WritableFile> whole_f;
95 std::string whole_path = test_path_ + "/0.txt";
96 ASSERT_OK(env_->NewWritableFile(whole_path, &whole_f, env_options_));
97 std::string whole_str = "0x61\n0x62\n0x63\n0x64\n0x65\n0x66\n";
98 ASSERT_OK(whole_f->Append(whole_str));
99 delete db_;
100 ASSERT_OK(DestroyDB(dbname_, options));
101 }
102
RunTraceAnalyzer(const std::vector<std::string> & args)103 void RunTraceAnalyzer(const std::vector<std::string>& args) {
104 char arg_buffer[kArgBufferSize];
105 char* argv[kMaxArgCount];
106 int argc = 0;
107 int cursor = 0;
108
109 for (const auto& arg : args) {
110 ASSERT_LE(cursor + arg.size() + 1, kArgBufferSize);
111 ASSERT_LE(argc + 1, kMaxArgCount);
112 snprintf(arg_buffer + cursor, arg.size() + 1, "%s", arg.c_str());
113
114 argv[argc++] = arg_buffer + cursor;
115 cursor += static_cast<int>(arg.size()) + 1;
116 }
117
118 ASSERT_EQ(0, ROCKSDB_NAMESPACE::trace_analyzer_tool(argc, argv));
119 }
120
CheckFileContent(const std::vector<std::string> & cnt,std::string file_path,bool full_content)121 void CheckFileContent(const std::vector<std::string>& cnt,
122 std::string file_path, bool full_content) {
123 ASSERT_OK(env_->FileExists(file_path));
124 std::unique_ptr<SequentialFile> f_ptr;
125 ASSERT_OK(env_->NewSequentialFile(file_path, &f_ptr, env_options_));
126
127 std::string get_line;
128 std::istringstream iss;
129 bool has_data = true;
130 std::vector<std::string> result;
131 uint32_t count;
132 Status s;
133 std::unique_ptr<FSSequentialFile> file =
134 NewLegacySequentialFileWrapper(f_ptr);
135 SequentialFileReader sf_reader(std::move(file), file_path,
136 4096 /* filereadahead_size */);
137
138 for (count = 0; ReadOneLine(&iss, &sf_reader, &get_line, &has_data, &s);
139 ++count) {
140 ASSERT_OK(s);
141 result.push_back(get_line);
142 }
143
144 ASSERT_EQ(cnt.size(), result.size());
145 for (int i = 0; i < static_cast<int>(result.size()); i++) {
146 if (full_content) {
147 ASSERT_EQ(result[i], cnt[i]);
148 } else {
149 ASSERT_EQ(result[i][0], cnt[i][0]);
150 }
151 }
152
153 return;
154 }
155
AnalyzeTrace(std::vector<std::string> & paras_diff,std::string output_path,std::string trace_path)156 void AnalyzeTrace(std::vector<std::string>& paras_diff,
157 std::string output_path, std::string trace_path) {
158 std::vector<std::string> paras = {"./trace_analyzer",
159 "-convert_to_human_readable_trace",
160 "-output_key_stats",
161 "-output_access_count_stats",
162 "-output_prefix=test",
163 "-output_prefix_cut=1",
164 "-output_time_series",
165 "-output_value_distribution",
166 "-output_qps_stats",
167 "-no_key",
168 "-no_print"};
169 for (auto& para : paras_diff) {
170 paras.push_back(para);
171 }
172 Status s = env_->FileExists(trace_path);
173 if (!s.ok()) {
174 GenerateTrace(trace_path);
175 }
176 env_->CreateDir(output_path);
177 RunTraceAnalyzer(paras);
178 }
179
180 ROCKSDB_NAMESPACE::Env* env_;
181 EnvOptions env_options_;
182 std::string test_path_;
183 std::string dbname_;
184 Random rnd_;
185 };
186
TEST_F(TraceAnalyzerTest,Get)187 TEST_F(TraceAnalyzerTest, Get) {
188 std::string trace_path = test_path_ + "/trace";
189 std::string output_path = test_path_ + "/get";
190 std::string file_path;
191 std::vector<std::string> paras = {"-analyze_get"};
192 paras.push_back("-output_dir=" + output_path);
193 paras.push_back("-trace_path=" + trace_path);
194 paras.push_back("-key_space_dir=" + test_path_);
195 AnalyzeTrace(paras, output_path, trace_path);
196
197 // check the key_stats file
198 std::vector<std::string> k_stats = {"0 10 0 1 1.000000", "0 10 1 1 1.000000"};
199 file_path = output_path + "/test-get-0-accessed_key_stats.txt";
200 CheckFileContent(k_stats, file_path, true);
201
202 // Check the access count distribution
203 std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
204 file_path = output_path + "/test-get-0-accessed_key_count_distribution.txt";
205 CheckFileContent(k_dist, file_path, true);
206
207 // Check the trace sequence
208 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
209 "0", "6", "7", "0"};
210 file_path = output_path + "/test-human_readable_trace.txt";
211 CheckFileContent(k_sequence, file_path, false);
212
213 // Check the prefix
214 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
215 "1 1 1 1.000000 1.000000 0x61"};
216 file_path = output_path + "/test-get-0-accessed_key_prefix_cut.txt";
217 CheckFileContent(k_prefix, file_path, true);
218
219 // Check the time series
220 std::vector<std::string> k_series = {"0 1533000630 0", "0 1533000630 1"};
221 file_path = output_path + "/test-get-0-time_series.txt";
222 CheckFileContent(k_series, file_path, false);
223
224 // Check the accessed key in whole key space
225 std::vector<std::string> k_whole_access = {"0 1"};
226 file_path = output_path + "/test-get-0-whole_key_stats.txt";
227 CheckFileContent(k_whole_access, file_path, true);
228
229 // Check the whole key prefix cut
230 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
231 "3 0x64", "4 0x65", "5 0x66"};
232 file_path = output_path + "/test-get-0-whole_key_prefix_cut.txt";
233 CheckFileContent(k_whole_prefix, file_path, true);
234
235 // Check the overall qps
236 std::vector<std::string> all_qps = {"1 0 0 0 0 0 0 0 1"};
237 file_path = output_path + "/test-qps_stats.txt";
238 CheckFileContent(all_qps, file_path, true);
239
240 // Check the qps of get
241 std::vector<std::string> get_qps = {"1"};
242 file_path = output_path + "/test-get-0-qps_stats.txt";
243 CheckFileContent(get_qps, file_path, true);
244
245 // Check the top k qps prefix cut
246 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
247 "The prefix: 0x61 Access count: 1"};
248 file_path = output_path + "/test-get-0-accessed_top_k_qps_prefix_cut.txt";
249 CheckFileContent(top_qps, file_path, true);
250 }
251
252 // Test analyzing of Put
TEST_F(TraceAnalyzerTest,Put)253 TEST_F(TraceAnalyzerTest, Put) {
254 std::string trace_path = test_path_ + "/trace";
255 std::string output_path = test_path_ + "/put";
256 std::string file_path;
257 std::vector<std::string> paras = {"-analyze_put"};
258 paras.push_back("-output_dir=" + output_path);
259 paras.push_back("-trace_path=" + trace_path);
260 paras.push_back("-key_space_dir=" + test_path_);
261 AnalyzeTrace(paras, output_path, trace_path);
262
263 // check the key_stats file
264 std::vector<std::string> k_stats = {"0 9 0 1 1.000000"};
265 file_path = output_path + "/test-put-0-accessed_key_stats.txt";
266 CheckFileContent(k_stats, file_path, true);
267
268 // Check the access count distribution
269 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
270 file_path = output_path + "/test-put-0-accessed_key_count_distribution.txt";
271 CheckFileContent(k_dist, file_path, true);
272
273 // Check the trace sequence
274 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
275 "0", "6", "7", "0"};
276 file_path = output_path + "/test-human_readable_trace.txt";
277 CheckFileContent(k_sequence, file_path, false);
278
279 // Check the prefix
280 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
281 file_path = output_path + "/test-put-0-accessed_key_prefix_cut.txt";
282 CheckFileContent(k_prefix, file_path, true);
283
284 // Check the time series
285 std::vector<std::string> k_series = {"1 1533056278 0"};
286 file_path = output_path + "/test-put-0-time_series.txt";
287 CheckFileContent(k_series, file_path, false);
288
289 // Check the accessed key in whole key space
290 std::vector<std::string> k_whole_access = {"0 1"};
291 file_path = output_path + "/test-put-0-whole_key_stats.txt";
292 CheckFileContent(k_whole_access, file_path, true);
293
294 // Check the whole key prefix cut
295 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
296 "3 0x64", "4 0x65", "5 0x66"};
297 file_path = output_path + "/test-put-0-whole_key_prefix_cut.txt";
298 CheckFileContent(k_whole_prefix, file_path, true);
299
300 // Check the overall qps
301 std::vector<std::string> all_qps = {"1 1 0 0 0 0 0 0 2"};
302 file_path = output_path + "/test-qps_stats.txt";
303 CheckFileContent(all_qps, file_path, true);
304
305 // Check the qps of Put
306 std::vector<std::string> get_qps = {"1"};
307 file_path = output_path + "/test-put-0-qps_stats.txt";
308 CheckFileContent(get_qps, file_path, true);
309
310 // Check the top k qps prefix cut
311 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
312 "The prefix: 0x61 Access count: 1"};
313 file_path = output_path + "/test-put-0-accessed_top_k_qps_prefix_cut.txt";
314 CheckFileContent(top_qps, file_path, true);
315
316 // Check the value size distribution
317 std::vector<std::string> value_dist = {
318 "Number_of_value_size_between 0 and 16 is: 1"};
319 file_path = output_path + "/test-put-0-accessed_value_size_distribution.txt";
320 CheckFileContent(value_dist, file_path, true);
321 }
322
323 // Test analyzing of delete
TEST_F(TraceAnalyzerTest,Delete)324 TEST_F(TraceAnalyzerTest, Delete) {
325 std::string trace_path = test_path_ + "/trace";
326 std::string output_path = test_path_ + "/delete";
327 std::string file_path;
328 std::vector<std::string> paras = {"-analyze_delete"};
329 paras.push_back("-output_dir=" + output_path);
330 paras.push_back("-trace_path=" + trace_path);
331 paras.push_back("-key_space_dir=" + test_path_);
332 AnalyzeTrace(paras, output_path, trace_path);
333
334 // check the key_stats file
335 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
336 file_path = output_path + "/test-delete-0-accessed_key_stats.txt";
337 CheckFileContent(k_stats, file_path, true);
338
339 // Check the access count distribution
340 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
341 file_path =
342 output_path + "/test-delete-0-accessed_key_count_distribution.txt";
343 CheckFileContent(k_dist, file_path, true);
344
345 // Check the trace sequence
346 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
347 "0", "6", "7", "0"};
348 file_path = output_path + "/test-human_readable_trace.txt";
349 CheckFileContent(k_sequence, file_path, false);
350
351 // Check the prefix
352 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
353 file_path = output_path + "/test-delete-0-accessed_key_prefix_cut.txt";
354 CheckFileContent(k_prefix, file_path, true);
355
356 // Check the time series
357 std::vector<std::string> k_series = {"2 1533000630 0"};
358 file_path = output_path + "/test-delete-0-time_series.txt";
359 CheckFileContent(k_series, file_path, false);
360
361 // Check the accessed key in whole key space
362 std::vector<std::string> k_whole_access = {"2 1"};
363 file_path = output_path + "/test-delete-0-whole_key_stats.txt";
364 CheckFileContent(k_whole_access, file_path, true);
365
366 // Check the whole key prefix cut
367 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
368 "3 0x64", "4 0x65", "5 0x66"};
369 file_path = output_path + "/test-delete-0-whole_key_prefix_cut.txt";
370 CheckFileContent(k_whole_prefix, file_path, true);
371
372 // Check the overall qps
373 std::vector<std::string> all_qps = {"1 1 1 0 0 0 0 0 3"};
374 file_path = output_path + "/test-qps_stats.txt";
375 CheckFileContent(all_qps, file_path, true);
376
377 // Check the qps of Delete
378 std::vector<std::string> get_qps = {"1"};
379 file_path = output_path + "/test-delete-0-qps_stats.txt";
380 CheckFileContent(get_qps, file_path, true);
381
382 // Check the top k qps prefix cut
383 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
384 "The prefix: 0x63 Access count: 1"};
385 file_path = output_path + "/test-delete-0-accessed_top_k_qps_prefix_cut.txt";
386 CheckFileContent(top_qps, file_path, true);
387 }
388
389 // Test analyzing of Merge
TEST_F(TraceAnalyzerTest,Merge)390 TEST_F(TraceAnalyzerTest, Merge) {
391 std::string trace_path = test_path_ + "/trace";
392 std::string output_path = test_path_ + "/merge";
393 std::string file_path;
394 std::vector<std::string> paras = {"-analyze_merge"};
395 paras.push_back("-output_dir=" + output_path);
396 paras.push_back("-trace_path=" + trace_path);
397 paras.push_back("-key_space_dir=" + test_path_);
398 AnalyzeTrace(paras, output_path, trace_path);
399
400 // check the key_stats file
401 std::vector<std::string> k_stats = {"0 20 0 1 1.000000"};
402 file_path = output_path + "/test-merge-0-accessed_key_stats.txt";
403 CheckFileContent(k_stats, file_path, true);
404
405 // Check the access count distribution
406 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
407 file_path = output_path + "/test-merge-0-accessed_key_count_distribution.txt";
408 CheckFileContent(k_dist, file_path, true);
409
410 // Check the trace sequence
411 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
412 "0", "6", "7", "0"};
413 file_path = output_path + "/test-human_readable_trace.txt";
414 CheckFileContent(k_sequence, file_path, false);
415
416 // Check the prefix
417 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
418 file_path = output_path + "/test-merge-0-accessed_key_prefix_cut.txt";
419 CheckFileContent(k_prefix, file_path, true);
420
421 // Check the time series
422 std::vector<std::string> k_series = {"5 1533000630 0"};
423 file_path = output_path + "/test-merge-0-time_series.txt";
424 CheckFileContent(k_series, file_path, false);
425
426 // Check the accessed key in whole key space
427 std::vector<std::string> k_whole_access = {"1 1"};
428 file_path = output_path + "/test-merge-0-whole_key_stats.txt";
429 CheckFileContent(k_whole_access, file_path, true);
430
431 // Check the whole key prefix cut
432 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
433 "3 0x64", "4 0x65", "5 0x66"};
434 file_path = output_path + "/test-merge-0-whole_key_prefix_cut.txt";
435 CheckFileContent(k_whole_prefix, file_path, true);
436
437 // Check the overall qps
438 std::vector<std::string> all_qps = {"1 1 1 0 0 1 0 0 4"};
439 file_path = output_path + "/test-qps_stats.txt";
440 CheckFileContent(all_qps, file_path, true);
441
442 // Check the qps of Merge
443 std::vector<std::string> get_qps = {"1"};
444 file_path = output_path + "/test-merge-0-qps_stats.txt";
445 CheckFileContent(get_qps, file_path, true);
446
447 // Check the top k qps prefix cut
448 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
449 "The prefix: 0x62 Access count: 1"};
450 file_path = output_path + "/test-merge-0-accessed_top_k_qps_prefix_cut.txt";
451 CheckFileContent(top_qps, file_path, true);
452
453 // Check the value size distribution
454 std::vector<std::string> value_dist = {
455 "Number_of_value_size_between 0 and 24 is: 1"};
456 file_path =
457 output_path + "/test-merge-0-accessed_value_size_distribution.txt";
458 CheckFileContent(value_dist, file_path, true);
459 }
460
461 // Test analyzing of SingleDelete
TEST_F(TraceAnalyzerTest,SingleDelete)462 TEST_F(TraceAnalyzerTest, SingleDelete) {
463 std::string trace_path = test_path_ + "/trace";
464 std::string output_path = test_path_ + "/single_delete";
465 std::string file_path;
466 std::vector<std::string> paras = {"-analyze_single_delete"};
467 paras.push_back("-output_dir=" + output_path);
468 paras.push_back("-trace_path=" + trace_path);
469 paras.push_back("-key_space_dir=" + test_path_);
470 AnalyzeTrace(paras, output_path, trace_path);
471
472 // check the key_stats file
473 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
474 file_path = output_path + "/test-single_delete-0-accessed_key_stats.txt";
475 CheckFileContent(k_stats, file_path, true);
476
477 // Check the access count distribution
478 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
479 file_path =
480 output_path + "/test-single_delete-0-accessed_key_count_distribution.txt";
481 CheckFileContent(k_dist, file_path, true);
482
483 // Check the trace sequence
484 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
485 "0", "6", "7", "0"};
486 file_path = output_path + "/test-human_readable_trace.txt";
487 CheckFileContent(k_sequence, file_path, false);
488
489 // Check the prefix
490 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
491 file_path = output_path + "/test-single_delete-0-accessed_key_prefix_cut.txt";
492 CheckFileContent(k_prefix, file_path, true);
493
494 // Check the time series
495 std::vector<std::string> k_series = {"3 1533000630 0"};
496 file_path = output_path + "/test-single_delete-0-time_series.txt";
497 CheckFileContent(k_series, file_path, false);
498
499 // Check the accessed key in whole key space
500 std::vector<std::string> k_whole_access = {"3 1"};
501 file_path = output_path + "/test-single_delete-0-whole_key_stats.txt";
502 CheckFileContent(k_whole_access, file_path, true);
503
504 // Check the whole key prefix cut
505 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
506 "3 0x64", "4 0x65", "5 0x66"};
507 file_path = output_path + "/test-single_delete-0-whole_key_prefix_cut.txt";
508 CheckFileContent(k_whole_prefix, file_path, true);
509
510 // Check the overall qps
511 std::vector<std::string> all_qps = {"1 1 1 1 0 1 0 0 5"};
512 file_path = output_path + "/test-qps_stats.txt";
513 CheckFileContent(all_qps, file_path, true);
514
515 // Check the qps of SingleDelete
516 std::vector<std::string> get_qps = {"1"};
517 file_path = output_path + "/test-single_delete-0-qps_stats.txt";
518 CheckFileContent(get_qps, file_path, true);
519
520 // Check the top k qps prefix cut
521 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
522 "The prefix: 0x64 Access count: 1"};
523 file_path =
524 output_path + "/test-single_delete-0-accessed_top_k_qps_prefix_cut.txt";
525 CheckFileContent(top_qps, file_path, true);
526 }
527
528 // Test analyzing of delete
TEST_F(TraceAnalyzerTest,DeleteRange)529 TEST_F(TraceAnalyzerTest, DeleteRange) {
530 std::string trace_path = test_path_ + "/trace";
531 std::string output_path = test_path_ + "/range_delete";
532 std::string file_path;
533 std::vector<std::string> paras = {"-analyze_range_delete"};
534 paras.push_back("-output_dir=" + output_path);
535 paras.push_back("-trace_path=" + trace_path);
536 paras.push_back("-key_space_dir=" + test_path_);
537 AnalyzeTrace(paras, output_path, trace_path);
538
539 // check the key_stats file
540 std::vector<std::string> k_stats = {"0 0 0 1 1.000000", "0 0 1 1 1.000000"};
541 file_path = output_path + "/test-range_delete-0-accessed_key_stats.txt";
542 CheckFileContent(k_stats, file_path, true);
543
544 // Check the access count distribution
545 std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
546 file_path =
547 output_path + "/test-range_delete-0-accessed_key_count_distribution.txt";
548 CheckFileContent(k_dist, file_path, true);
549
550 // Check the trace sequence
551 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
552 "0", "6", "7", "0"};
553 file_path = output_path + "/test-human_readable_trace.txt";
554 CheckFileContent(k_sequence, file_path, false);
555
556 // Check the prefix
557 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
558 "1 1 1 1.000000 1.000000 0x65"};
559 file_path = output_path + "/test-range_delete-0-accessed_key_prefix_cut.txt";
560 CheckFileContent(k_prefix, file_path, true);
561
562 // Check the time series
563 std::vector<std::string> k_series = {"4 1533000630 0", "4 1533060100 1"};
564 file_path = output_path + "/test-range_delete-0-time_series.txt";
565 CheckFileContent(k_series, file_path, false);
566
567 // Check the accessed key in whole key space
568 std::vector<std::string> k_whole_access = {"4 1", "5 1"};
569 file_path = output_path + "/test-range_delete-0-whole_key_stats.txt";
570 CheckFileContent(k_whole_access, file_path, true);
571
572 // Check the whole key prefix cut
573 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
574 "3 0x64", "4 0x65", "5 0x66"};
575 file_path = output_path + "/test-range_delete-0-whole_key_prefix_cut.txt";
576 CheckFileContent(k_whole_prefix, file_path, true);
577
578 // Check the overall qps
579 std::vector<std::string> all_qps = {"1 1 1 1 2 1 0 0 7"};
580 file_path = output_path + "/test-qps_stats.txt";
581 CheckFileContent(all_qps, file_path, true);
582
583 // Check the qps of DeleteRange
584 std::vector<std::string> get_qps = {"2"};
585 file_path = output_path + "/test-range_delete-0-qps_stats.txt";
586 CheckFileContent(get_qps, file_path, true);
587
588 // Check the top k qps prefix cut
589 std::vector<std::string> top_qps = {"At time: 0 with QPS: 2",
590 "The prefix: 0x65 Access count: 1",
591 "The prefix: 0x66 Access count: 1"};
592 file_path =
593 output_path + "/test-range_delete-0-accessed_top_k_qps_prefix_cut.txt";
594 CheckFileContent(top_qps, file_path, true);
595 }
596
597 // Test analyzing of Iterator
TEST_F(TraceAnalyzerTest,Iterator)598 TEST_F(TraceAnalyzerTest, Iterator) {
599 std::string trace_path = test_path_ + "/trace";
600 std::string output_path = test_path_ + "/iterator";
601 std::string file_path;
602 std::vector<std::string> paras = {"-analyze_iterator"};
603 paras.push_back("-output_dir=" + output_path);
604 paras.push_back("-trace_path=" + trace_path);
605 paras.push_back("-key_space_dir=" + test_path_);
606 AnalyzeTrace(paras, output_path, trace_path);
607
608 // Check the output of Seek
609 // check the key_stats file
610 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
611 file_path = output_path + "/test-iterator_Seek-0-accessed_key_stats.txt";
612 CheckFileContent(k_stats, file_path, true);
613
614 // Check the access count distribution
615 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
616 file_path =
617 output_path + "/test-iterator_Seek-0-accessed_key_count_distribution.txt";
618 CheckFileContent(k_dist, file_path, true);
619
620 // Check the trace sequence
621 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
622 "0", "6", "7", "0"};
623 file_path = output_path + "/test-human_readable_trace.txt";
624 CheckFileContent(k_sequence, file_path, false);
625
626 // Check the prefix
627 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
628 file_path = output_path + "/test-iterator_Seek-0-accessed_key_prefix_cut.txt";
629 CheckFileContent(k_prefix, file_path, true);
630
631 // Check the time series
632 std::vector<std::string> k_series = {"6 1 0"};
633 file_path = output_path + "/test-iterator_Seek-0-time_series.txt";
634 CheckFileContent(k_series, file_path, false);
635
636 // Check the accessed key in whole key space
637 std::vector<std::string> k_whole_access = {"0 1"};
638 file_path = output_path + "/test-iterator_Seek-0-whole_key_stats.txt";
639 CheckFileContent(k_whole_access, file_path, true);
640
641 // Check the whole key prefix cut
642 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
643 "3 0x64", "4 0x65", "5 0x66"};
644 file_path = output_path + "/test-iterator_Seek-0-whole_key_prefix_cut.txt";
645 CheckFileContent(k_whole_prefix, file_path, true);
646
647 // Check the overall qps
648 std::vector<std::string> all_qps = {"1 1 1 1 2 1 1 1 9"};
649 file_path = output_path + "/test-qps_stats.txt";
650 CheckFileContent(all_qps, file_path, true);
651
652 // Check the qps of Iterator_Seek
653 std::vector<std::string> get_qps = {"1"};
654 file_path = output_path + "/test-iterator_Seek-0-qps_stats.txt";
655 CheckFileContent(get_qps, file_path, true);
656
657 // Check the top k qps prefix cut
658 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
659 "The prefix: 0x61 Access count: 1"};
660 file_path =
661 output_path + "/test-iterator_Seek-0-accessed_top_k_qps_prefix_cut.txt";
662 CheckFileContent(top_qps, file_path, true);
663
664 // Check the output of SeekForPrev
665 // check the key_stats file
666 k_stats = {"0 0 0 1 1.000000"};
667 file_path =
668 output_path + "/test-iterator_SeekForPrev-0-accessed_key_stats.txt";
669 CheckFileContent(k_stats, file_path, true);
670
671 // Check the access count distribution
672 k_dist = {"access_count: 1 num: 1"};
673 file_path =
674 output_path +
675 "/test-iterator_SeekForPrev-0-accessed_key_count_distribution.txt";
676 CheckFileContent(k_dist, file_path, true);
677
678 // Check the prefix
679 k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
680 file_path =
681 output_path + "/test-iterator_SeekForPrev-0-accessed_key_prefix_cut.txt";
682 CheckFileContent(k_prefix, file_path, true);
683
684 // Check the time series
685 k_series = {"7 0 0"};
686 file_path = output_path + "/test-iterator_SeekForPrev-0-time_series.txt";
687 CheckFileContent(k_series, file_path, false);
688
689 // Check the accessed key in whole key space
690 k_whole_access = {"1 1"};
691 file_path = output_path + "/test-iterator_SeekForPrev-0-whole_key_stats.txt";
692 CheckFileContent(k_whole_access, file_path, true);
693
694 // Check the whole key prefix cut
695 k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63", "3 0x64", "4 0x65", "5 0x66"};
696 file_path =
697 output_path + "/test-iterator_SeekForPrev-0-whole_key_prefix_cut.txt";
698 CheckFileContent(k_whole_prefix, file_path, true);
699
700 // Check the qps of Iterator_SeekForPrev
701 get_qps = {"1"};
702 file_path = output_path + "/test-iterator_SeekForPrev-0-qps_stats.txt";
703 CheckFileContent(get_qps, file_path, true);
704
705 // Check the top k qps prefix cut
706 top_qps = {"At time: 0 with QPS: 1", "The prefix: 0x62 Access count: 1"};
707 file_path = output_path +
708 "/test-iterator_SeekForPrev-0-accessed_top_k_qps_prefix_cut.txt";
709 CheckFileContent(top_qps, file_path, true);
710 }
711
712 } // namespace ROCKSDB_NAMESPACE
713
main(int argc,char ** argv)714 int main(int argc, char** argv) {
715 ::testing::InitGoogleTest(&argc, argv);
716 return RUN_ALL_TESTS();
717 }
718 #endif // GFLAG
719 #else
720 #include <stdio.h>
721
main(int,char **)722 int main(int /*argc*/, char** /*argv*/) {
723 fprintf(stderr, "Trace_analyzer test is not supported in ROCKSDB_LITE\n");
724 return 0;
725 }
726
727 #endif // !ROCKSDB_LITE return RUN_ALL_TESTS();
728