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_); 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 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 = {"-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 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 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 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 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 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 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 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 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