]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/tools/trace_analyzer_test.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / tools / trace_analyzer_test.cc
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>
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:
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_).PermitUncheckedError();
51 dbname_ = test_path_ + "/db";
52 }
53
54 ~TraceAnalyzerTest() override {}
55
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
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
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
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 ASSERT_OK(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
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 = {
192 "-analyze_get=true", "-analyze_put=false",
193 "-analyze_delete=false", "-analyze_single_delete=false",
194 "-analyze_range_delete=false", "-analyze_iterator=false"};
195 paras.push_back("-output_dir=" + output_path);
196 paras.push_back("-trace_path=" + trace_path);
197 paras.push_back("-key_space_dir=" + test_path_);
198 AnalyzeTrace(paras, output_path, trace_path);
199
200 // check the key_stats file
201 std::vector<std::string> k_stats = {"0 10 0 1 1.000000", "0 10 1 1 1.000000"};
202 file_path = output_path + "/test-get-0-accessed_key_stats.txt";
203 CheckFileContent(k_stats, file_path, true);
204
205 // Check the access count distribution
206 std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
207 file_path = output_path + "/test-get-0-accessed_key_count_distribution.txt";
208 CheckFileContent(k_dist, file_path, true);
209
210 // Check the trace sequence
211 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
212 "0", "6", "7", "0"};
213 file_path = output_path + "/test-human_readable_trace.txt";
214 CheckFileContent(k_sequence, file_path, false);
215
216 // Check the prefix
217 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
218 "1 1 1 1.000000 1.000000 0x61"};
219 file_path = output_path + "/test-get-0-accessed_key_prefix_cut.txt";
220 CheckFileContent(k_prefix, file_path, true);
221
222 // Check the time series
223 std::vector<std::string> k_series = {"0 1533000630 0", "0 1533000630 1"};
224 file_path = output_path + "/test-get-0-time_series.txt";
225 CheckFileContent(k_series, file_path, false);
226
227 // Check the accessed key in whole key space
228 std::vector<std::string> k_whole_access = {"0 1"};
229 file_path = output_path + "/test-get-0-whole_key_stats.txt";
230 CheckFileContent(k_whole_access, file_path, true);
231
232 // Check the whole key prefix cut
233 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
234 "3 0x64", "4 0x65", "5 0x66"};
235 file_path = output_path + "/test-get-0-whole_key_prefix_cut.txt";
236 CheckFileContent(k_whole_prefix, file_path, true);
237
238 // Check the overall qps
239 std::vector<std::string> all_qps = {"1 0 0 0 0 0 0 0 1"};
240 file_path = output_path + "/test-qps_stats.txt";
241 CheckFileContent(all_qps, file_path, true);
242
243 // Check the qps of get
244 std::vector<std::string> get_qps = {"1"};
245 file_path = output_path + "/test-get-0-qps_stats.txt";
246 CheckFileContent(get_qps, file_path, true);
247
248 // Check the top k qps prefix cut
249 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
250 "The prefix: 0x61 Access count: 1"};
251 file_path = output_path + "/test-get-0-accessed_top_k_qps_prefix_cut.txt";
252 CheckFileContent(top_qps, file_path, true);
253 }
254
255 // Test analyzing of Put
256 TEST_F(TraceAnalyzerTest, Put) {
257 std::string trace_path = test_path_ + "/trace";
258 std::string output_path = test_path_ + "/put";
259 std::string file_path;
260 std::vector<std::string> paras = {
261 "-analyze_get=false", "-analyze_put=true",
262 "-analyze_delete=false", "-analyze_single_delete=false",
263 "-analyze_range_delete=false", "-analyze_iterator=false"};
264 paras.push_back("-output_dir=" + output_path);
265 paras.push_back("-trace_path=" + trace_path);
266 paras.push_back("-key_space_dir=" + test_path_);
267 AnalyzeTrace(paras, output_path, trace_path);
268
269 // check the key_stats file
270 std::vector<std::string> k_stats = {"0 9 0 1 1.000000"};
271 file_path = output_path + "/test-put-0-accessed_key_stats.txt";
272 CheckFileContent(k_stats, file_path, true);
273
274 // Check the access count distribution
275 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
276 file_path = output_path + "/test-put-0-accessed_key_count_distribution.txt";
277 CheckFileContent(k_dist, file_path, true);
278
279 // Check the trace sequence
280 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
281 "0", "6", "7", "0"};
282 file_path = output_path + "/test-human_readable_trace.txt";
283 CheckFileContent(k_sequence, file_path, false);
284
285 // Check the prefix
286 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
287 file_path = output_path + "/test-put-0-accessed_key_prefix_cut.txt";
288 CheckFileContent(k_prefix, file_path, true);
289
290 // Check the time series
291 std::vector<std::string> k_series = {"1 1533056278 0"};
292 file_path = output_path + "/test-put-0-time_series.txt";
293 CheckFileContent(k_series, file_path, false);
294
295 // Check the accessed key in whole key space
296 std::vector<std::string> k_whole_access = {"0 1"};
297 file_path = output_path + "/test-put-0-whole_key_stats.txt";
298 CheckFileContent(k_whole_access, file_path, true);
299
300 // Check the whole key prefix cut
301 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
302 "3 0x64", "4 0x65", "5 0x66"};
303 file_path = output_path + "/test-put-0-whole_key_prefix_cut.txt";
304 CheckFileContent(k_whole_prefix, file_path, true);
305
306 // Check the overall qps
307 std::vector<std::string> all_qps = {"0 1 0 0 0 0 0 0 1"};
308 file_path = output_path + "/test-qps_stats.txt";
309 CheckFileContent(all_qps, file_path, true);
310
311 // Check the qps of Put
312 std::vector<std::string> get_qps = {"1"};
313 file_path = output_path + "/test-put-0-qps_stats.txt";
314 CheckFileContent(get_qps, file_path, true);
315
316 // Check the top k qps prefix cut
317 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
318 "The prefix: 0x61 Access count: 1"};
319 file_path = output_path + "/test-put-0-accessed_top_k_qps_prefix_cut.txt";
320 CheckFileContent(top_qps, file_path, true);
321
322 // Check the value size distribution
323 std::vector<std::string> value_dist = {
324 "Number_of_value_size_between 0 and 16 is: 1"};
325 file_path = output_path + "/test-put-0-accessed_value_size_distribution.txt";
326 CheckFileContent(value_dist, file_path, true);
327 }
328
329 // Test analyzing of delete
330 TEST_F(TraceAnalyzerTest, Delete) {
331 std::string trace_path = test_path_ + "/trace";
332 std::string output_path = test_path_ + "/delete";
333 std::string file_path;
334 std::vector<std::string> paras = {
335 "-analyze_get=false", "-analyze_put=false",
336 "-analyze_delete=true", "-analyze_single_delete=false",
337 "-analyze_range_delete=false", "-analyze_iterator=false"};
338 paras.push_back("-output_dir=" + output_path);
339 paras.push_back("-trace_path=" + trace_path);
340 paras.push_back("-key_space_dir=" + test_path_);
341 AnalyzeTrace(paras, output_path, trace_path);
342
343 // check the key_stats file
344 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
345 file_path = output_path + "/test-delete-0-accessed_key_stats.txt";
346 CheckFileContent(k_stats, file_path, true);
347
348 // Check the access count distribution
349 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
350 file_path =
351 output_path + "/test-delete-0-accessed_key_count_distribution.txt";
352 CheckFileContent(k_dist, file_path, true);
353
354 // Check the trace sequence
355 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
356 "0", "6", "7", "0"};
357 file_path = output_path + "/test-human_readable_trace.txt";
358 CheckFileContent(k_sequence, file_path, false);
359
360 // Check the prefix
361 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
362 file_path = output_path + "/test-delete-0-accessed_key_prefix_cut.txt";
363 CheckFileContent(k_prefix, file_path, true);
364
365 // Check the time series
366 std::vector<std::string> k_series = {"2 1533000630 0"};
367 file_path = output_path + "/test-delete-0-time_series.txt";
368 CheckFileContent(k_series, file_path, false);
369
370 // Check the accessed key in whole key space
371 std::vector<std::string> k_whole_access = {"2 1"};
372 file_path = output_path + "/test-delete-0-whole_key_stats.txt";
373 CheckFileContent(k_whole_access, file_path, true);
374
375 // Check the whole key prefix cut
376 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
377 "3 0x64", "4 0x65", "5 0x66"};
378 file_path = output_path + "/test-delete-0-whole_key_prefix_cut.txt";
379 CheckFileContent(k_whole_prefix, file_path, true);
380
381 // Check the overall qps
382 std::vector<std::string> all_qps = {"0 0 1 0 0 0 0 0 1"};
383 file_path = output_path + "/test-qps_stats.txt";
384 CheckFileContent(all_qps, file_path, true);
385
386 // Check the qps of Delete
387 std::vector<std::string> get_qps = {"1"};
388 file_path = output_path + "/test-delete-0-qps_stats.txt";
389 CheckFileContent(get_qps, file_path, true);
390
391 // Check the top k qps prefix cut
392 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
393 "The prefix: 0x63 Access count: 1"};
394 file_path = output_path + "/test-delete-0-accessed_top_k_qps_prefix_cut.txt";
395 CheckFileContent(top_qps, file_path, true);
396 }
397
398 // Test analyzing of Merge
399 TEST_F(TraceAnalyzerTest, Merge) {
400 std::string trace_path = test_path_ + "/trace";
401 std::string output_path = test_path_ + "/merge";
402 std::string file_path;
403 std::vector<std::string> paras = {
404 "-analyze_get=false", "-analyze_put=false",
405 "-analyze_delete=false", "-analyze_merge=true",
406 "-analyze_single_delete=false", "-analyze_range_delete=false",
407 "-analyze_iterator=false"};
408 paras.push_back("-output_dir=" + output_path);
409 paras.push_back("-trace_path=" + trace_path);
410 paras.push_back("-key_space_dir=" + test_path_);
411 AnalyzeTrace(paras, output_path, trace_path);
412
413 // check the key_stats file
414 std::vector<std::string> k_stats = {"0 20 0 1 1.000000"};
415 file_path = output_path + "/test-merge-0-accessed_key_stats.txt";
416 CheckFileContent(k_stats, file_path, true);
417
418 // Check the access count distribution
419 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
420 file_path = output_path + "/test-merge-0-accessed_key_count_distribution.txt";
421 CheckFileContent(k_dist, file_path, true);
422
423 // Check the trace sequence
424 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
425 "0", "6", "7", "0"};
426 file_path = output_path + "/test-human_readable_trace.txt";
427 CheckFileContent(k_sequence, file_path, false);
428
429 // Check the prefix
430 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
431 file_path = output_path + "/test-merge-0-accessed_key_prefix_cut.txt";
432 CheckFileContent(k_prefix, file_path, true);
433
434 // Check the time series
435 std::vector<std::string> k_series = {"5 1533000630 0"};
436 file_path = output_path + "/test-merge-0-time_series.txt";
437 CheckFileContent(k_series, file_path, false);
438
439 // Check the accessed key in whole key space
440 std::vector<std::string> k_whole_access = {"1 1"};
441 file_path = output_path + "/test-merge-0-whole_key_stats.txt";
442 CheckFileContent(k_whole_access, file_path, true);
443
444 // Check the whole key prefix cut
445 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
446 "3 0x64", "4 0x65", "5 0x66"};
447 file_path = output_path + "/test-merge-0-whole_key_prefix_cut.txt";
448 CheckFileContent(k_whole_prefix, file_path, true);
449
450 // Check the overall qps
451 std::vector<std::string> all_qps = {"0 0 0 0 0 1 0 0 1"};
452 file_path = output_path + "/test-qps_stats.txt";
453 CheckFileContent(all_qps, file_path, true);
454
455 // Check the qps of Merge
456 std::vector<std::string> get_qps = {"1"};
457 file_path = output_path + "/test-merge-0-qps_stats.txt";
458 CheckFileContent(get_qps, file_path, true);
459
460 // Check the top k qps prefix cut
461 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
462 "The prefix: 0x62 Access count: 1"};
463 file_path = output_path + "/test-merge-0-accessed_top_k_qps_prefix_cut.txt";
464 CheckFileContent(top_qps, file_path, true);
465
466 // Check the value size distribution
467 std::vector<std::string> value_dist = {
468 "Number_of_value_size_between 0 and 24 is: 1"};
469 file_path =
470 output_path + "/test-merge-0-accessed_value_size_distribution.txt";
471 CheckFileContent(value_dist, file_path, true);
472 }
473
474 // Test analyzing of SingleDelete
475 TEST_F(TraceAnalyzerTest, SingleDelete) {
476 std::string trace_path = test_path_ + "/trace";
477 std::string output_path = test_path_ + "/single_delete";
478 std::string file_path;
479 std::vector<std::string> paras = {
480 "-analyze_get=false", "-analyze_put=false",
481 "-analyze_delete=false", "-analyze_merge=false",
482 "-analyze_single_delete=true", "-analyze_range_delete=false",
483 "-analyze_iterator=false"};
484 paras.push_back("-output_dir=" + output_path);
485 paras.push_back("-trace_path=" + trace_path);
486 paras.push_back("-key_space_dir=" + test_path_);
487 AnalyzeTrace(paras, output_path, trace_path);
488
489 // check the key_stats file
490 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
491 file_path = output_path + "/test-single_delete-0-accessed_key_stats.txt";
492 CheckFileContent(k_stats, file_path, true);
493
494 // Check the access count distribution
495 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
496 file_path =
497 output_path + "/test-single_delete-0-accessed_key_count_distribution.txt";
498 CheckFileContent(k_dist, file_path, true);
499
500 // Check the trace sequence
501 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
502 "0", "6", "7", "0"};
503 file_path = output_path + "/test-human_readable_trace.txt";
504 CheckFileContent(k_sequence, file_path, false);
505
506 // Check the prefix
507 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
508 file_path = output_path + "/test-single_delete-0-accessed_key_prefix_cut.txt";
509 CheckFileContent(k_prefix, file_path, true);
510
511 // Check the time series
512 std::vector<std::string> k_series = {"3 1533000630 0"};
513 file_path = output_path + "/test-single_delete-0-time_series.txt";
514 CheckFileContent(k_series, file_path, false);
515
516 // Check the accessed key in whole key space
517 std::vector<std::string> k_whole_access = {"3 1"};
518 file_path = output_path + "/test-single_delete-0-whole_key_stats.txt";
519 CheckFileContent(k_whole_access, file_path, true);
520
521 // Check the whole key prefix cut
522 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
523 "3 0x64", "4 0x65", "5 0x66"};
524 file_path = output_path + "/test-single_delete-0-whole_key_prefix_cut.txt";
525 CheckFileContent(k_whole_prefix, file_path, true);
526
527 // Check the overall qps
528 std::vector<std::string> all_qps = {"0 0 0 1 0 0 0 0 1"};
529 file_path = output_path + "/test-qps_stats.txt";
530 CheckFileContent(all_qps, file_path, true);
531
532 // Check the qps of SingleDelete
533 std::vector<std::string> get_qps = {"1"};
534 file_path = output_path + "/test-single_delete-0-qps_stats.txt";
535 CheckFileContent(get_qps, file_path, true);
536
537 // Check the top k qps prefix cut
538 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
539 "The prefix: 0x64 Access count: 1"};
540 file_path =
541 output_path + "/test-single_delete-0-accessed_top_k_qps_prefix_cut.txt";
542 CheckFileContent(top_qps, file_path, true);
543 }
544
545 // Test analyzing of delete
546 TEST_F(TraceAnalyzerTest, DeleteRange) {
547 std::string trace_path = test_path_ + "/trace";
548 std::string output_path = test_path_ + "/range_delete";
549 std::string file_path;
550 std::vector<std::string> paras = {
551 "-analyze_get=false", "-analyze_put=false",
552 "-analyze_delete=false", "-analyze_merge=false",
553 "-analyze_single_delete=false", "-analyze_range_delete=true",
554 "-analyze_iterator=false"};
555 paras.push_back("-output_dir=" + output_path);
556 paras.push_back("-trace_path=" + trace_path);
557 paras.push_back("-key_space_dir=" + test_path_);
558 AnalyzeTrace(paras, output_path, trace_path);
559
560 // check the key_stats file
561 std::vector<std::string> k_stats = {"0 0 0 1 1.000000", "0 0 1 1 1.000000"};
562 file_path = output_path + "/test-range_delete-0-accessed_key_stats.txt";
563 CheckFileContent(k_stats, file_path, true);
564
565 // Check the access count distribution
566 std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
567 file_path =
568 output_path + "/test-range_delete-0-accessed_key_count_distribution.txt";
569 CheckFileContent(k_dist, file_path, true);
570
571 // Check the trace sequence
572 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
573 "0", "6", "7", "0"};
574 file_path = output_path + "/test-human_readable_trace.txt";
575 CheckFileContent(k_sequence, file_path, false);
576
577 // Check the prefix
578 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
579 "1 1 1 1.000000 1.000000 0x65"};
580 file_path = output_path + "/test-range_delete-0-accessed_key_prefix_cut.txt";
581 CheckFileContent(k_prefix, file_path, true);
582
583 // Check the time series
584 std::vector<std::string> k_series = {"4 1533000630 0", "4 1533060100 1"};
585 file_path = output_path + "/test-range_delete-0-time_series.txt";
586 CheckFileContent(k_series, file_path, false);
587
588 // Check the accessed key in whole key space
589 std::vector<std::string> k_whole_access = {"4 1", "5 1"};
590 file_path = output_path + "/test-range_delete-0-whole_key_stats.txt";
591 CheckFileContent(k_whole_access, file_path, true);
592
593 // Check the whole key prefix cut
594 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
595 "3 0x64", "4 0x65", "5 0x66"};
596 file_path = output_path + "/test-range_delete-0-whole_key_prefix_cut.txt";
597 CheckFileContent(k_whole_prefix, file_path, true);
598
599 // Check the overall qps
600 std::vector<std::string> all_qps = {"0 0 0 0 2 0 0 0 2"};
601 file_path = output_path + "/test-qps_stats.txt";
602 CheckFileContent(all_qps, file_path, true);
603
604 // Check the qps of DeleteRange
605 std::vector<std::string> get_qps = {"2"};
606 file_path = output_path + "/test-range_delete-0-qps_stats.txt";
607 CheckFileContent(get_qps, file_path, true);
608
609 // Check the top k qps prefix cut
610 std::vector<std::string> top_qps = {"At time: 0 with QPS: 2",
611 "The prefix: 0x65 Access count: 1",
612 "The prefix: 0x66 Access count: 1"};
613 file_path =
614 output_path + "/test-range_delete-0-accessed_top_k_qps_prefix_cut.txt";
615 CheckFileContent(top_qps, file_path, true);
616 }
617
618 // Test analyzing of Iterator
619 TEST_F(TraceAnalyzerTest, Iterator) {
620 std::string trace_path = test_path_ + "/trace";
621 std::string output_path = test_path_ + "/iterator";
622 std::string file_path;
623 std::vector<std::string> paras = {
624 "-analyze_get=false", "-analyze_put=false",
625 "-analyze_delete=false", "-analyze_merge=false",
626 "-analyze_single_delete=false", "-analyze_range_delete=false",
627 "-analyze_iterator=true"};
628 paras.push_back("-output_dir=" + output_path);
629 paras.push_back("-trace_path=" + trace_path);
630 paras.push_back("-key_space_dir=" + test_path_);
631 AnalyzeTrace(paras, output_path, trace_path);
632
633 // Check the output of Seek
634 // check the key_stats file
635 std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
636 file_path = output_path + "/test-iterator_Seek-0-accessed_key_stats.txt";
637 CheckFileContent(k_stats, file_path, true);
638
639 // Check the access count distribution
640 std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
641 file_path =
642 output_path + "/test-iterator_Seek-0-accessed_key_count_distribution.txt";
643 CheckFileContent(k_dist, file_path, true);
644
645 // Check the trace sequence
646 std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
647 "0", "6", "7", "0"};
648 file_path = output_path + "/test-human_readable_trace.txt";
649 CheckFileContent(k_sequence, file_path, false);
650
651 // Check the prefix
652 std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
653 file_path = output_path + "/test-iterator_Seek-0-accessed_key_prefix_cut.txt";
654 CheckFileContent(k_prefix, file_path, true);
655
656 // Check the time series
657 std::vector<std::string> k_series = {"6 1 0"};
658 file_path = output_path + "/test-iterator_Seek-0-time_series.txt";
659 CheckFileContent(k_series, file_path, false);
660
661 // Check the accessed key in whole key space
662 std::vector<std::string> k_whole_access = {"0 1"};
663 file_path = output_path + "/test-iterator_Seek-0-whole_key_stats.txt";
664 CheckFileContent(k_whole_access, file_path, true);
665
666 // Check the whole key prefix cut
667 std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
668 "3 0x64", "4 0x65", "5 0x66"};
669 file_path = output_path + "/test-iterator_Seek-0-whole_key_prefix_cut.txt";
670 CheckFileContent(k_whole_prefix, file_path, true);
671
672 // Check the overall qps
673 std::vector<std::string> all_qps = {"0 0 0 0 0 0 1 1 2"};
674 file_path = output_path + "/test-qps_stats.txt";
675 CheckFileContent(all_qps, file_path, true);
676
677 // Check the qps of Iterator_Seek
678 std::vector<std::string> get_qps = {"1"};
679 file_path = output_path + "/test-iterator_Seek-0-qps_stats.txt";
680 CheckFileContent(get_qps, file_path, true);
681
682 // Check the top k qps prefix cut
683 std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
684 "The prefix: 0x61 Access count: 1"};
685 file_path =
686 output_path + "/test-iterator_Seek-0-accessed_top_k_qps_prefix_cut.txt";
687 CheckFileContent(top_qps, file_path, true);
688
689 // Check the output of SeekForPrev
690 // check the key_stats file
691 k_stats = {"0 0 0 1 1.000000"};
692 file_path =
693 output_path + "/test-iterator_SeekForPrev-0-accessed_key_stats.txt";
694 CheckFileContent(k_stats, file_path, true);
695
696 // Check the access count distribution
697 k_dist = {"access_count: 1 num: 1"};
698 file_path =
699 output_path +
700 "/test-iterator_SeekForPrev-0-accessed_key_count_distribution.txt";
701 CheckFileContent(k_dist, file_path, true);
702
703 // Check the prefix
704 k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
705 file_path =
706 output_path + "/test-iterator_SeekForPrev-0-accessed_key_prefix_cut.txt";
707 CheckFileContent(k_prefix, file_path, true);
708
709 // Check the time series
710 k_series = {"7 0 0"};
711 file_path = output_path + "/test-iterator_SeekForPrev-0-time_series.txt";
712 CheckFileContent(k_series, file_path, false);
713
714 // Check the accessed key in whole key space
715 k_whole_access = {"1 1"};
716 file_path = output_path + "/test-iterator_SeekForPrev-0-whole_key_stats.txt";
717 CheckFileContent(k_whole_access, file_path, true);
718
719 // Check the whole key prefix cut
720 k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63", "3 0x64", "4 0x65", "5 0x66"};
721 file_path =
722 output_path + "/test-iterator_SeekForPrev-0-whole_key_prefix_cut.txt";
723 CheckFileContent(k_whole_prefix, file_path, true);
724
725 // Check the qps of Iterator_SeekForPrev
726 get_qps = {"1"};
727 file_path = output_path + "/test-iterator_SeekForPrev-0-qps_stats.txt";
728 CheckFileContent(get_qps, file_path, true);
729
730 // Check the top k qps prefix cut
731 top_qps = {"At time: 0 with QPS: 1", "The prefix: 0x62 Access count: 1"};
732 file_path = output_path +
733 "/test-iterator_SeekForPrev-0-accessed_top_k_qps_prefix_cut.txt";
734 CheckFileContent(top_qps, file_path, true);
735 }
736
737 } // namespace ROCKSDB_NAMESPACE
738
739 int main(int argc, char** argv) {
740 ::testing::InitGoogleTest(&argc, argv);
741 return RUN_ALL_TESTS();
742 }
743 #endif // GFLAG
744 #else
745 #include <stdio.h>
746
747 int main(int /*argc*/, char** /*argv*/) {
748 fprintf(stderr, "Trace_analyzer test is not supported in ROCKSDB_LITE\n");
749 return 0;
750 }
751
752 #endif // !ROCKSDB_LITE return RUN_ALL_TESTS();