YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector_test.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
25
#ifndef ROCKSDB_LITE
26
27
#include <algorithm>
28
#include <vector>
29
30
#include "yb/rocksdb/table_properties.h"
31
#include "yb/rocksdb/util/random.h"
32
#include "yb/rocksdb/utilities/table_properties_collectors.h"
33
34
#include "yb/util/stopwatch.h"
35
#include "yb/util/tsan_util.h"
36
37
1
int main(int argc, char** argv) {
38
1
  const int kWindowSizes[] =
39
1
      {1000, 10000, 10000, 127, 128, 129, 255, 256, 257, 2, 10000};
40
1
  const int kDeletionTriggers[] =
41
1
      {500, 9500, 4323, 47, 61, 128, 250, 250, 250, 2, 2};
42
1
  rocksdb::TablePropertiesCollectorFactory::Context context;
43
1
  context.column_family_id =
44
1
      rocksdb::TablePropertiesCollectorFactory::Context::kUnknownColumnFamily;
45
46
1
  std::vector<int> window_sizes;
47
1
  std::vector<int> deletion_triggers;
48
  // deterministic tests
49
10
  for (int test = 0; test < 9; ++test) {
50
9
    window_sizes.emplace_back(kWindowSizes[test]);
51
9
    deletion_triggers.emplace_back(kDeletionTriggers[test]);
52
9
  }
53
54
55
  // Lower number of runs for tsan due to low perf.
56
1
  constexpr int kNumRandomTests = yb::NonTsanVsTsan(100, 20);
57
58
  // randomize tests
59
1
  rocksdb::Random rnd(301);
60
1
  const int kMaxTestSize = 100000l;
61
101
  for (int random_test = 0; random_test < kNumRandomTests; random_test++) {
62
100
    int window_size = rnd.Uniform(kMaxTestSize) + 1;
63
100
    int deletion_trigger = rnd.Uniform(window_size);
64
100
    window_sizes.emplace_back(window_size);
65
100
    deletion_triggers.emplace_back(deletion_trigger);
66
100
  }
67
68
1
  assert(window_sizes.size() == deletion_triggers.size());
69
70
110
  for (size_t test = 0; test < window_sizes.size(); ++test) {
71
109
    const int kBucketSize = 128;
72
109
    const int kWindowSize = window_sizes[test];
73
109
    const int kPaddedWindowSize =
74
109
        kBucketSize * ((window_sizes[test] + kBucketSize - 1) / kBucketSize);
75
109
    const int kNumDeletionTrigger = deletion_triggers[test];
76
109
    const int kBias = (kNumDeletionTrigger + kBucketSize - 1) / kBucketSize;
77
    // Simple test
78
109
    LOG_TIMING(INFO, "TEST1") {
79
109
      std::unique_ptr<rocksdb::TablePropertiesCollector> collector;
80
109
      auto factory = rocksdb::NewCompactOnDeletionCollectorFactory(
81
109
          kWindowSize, kNumDeletionTrigger);
82
109
      collector.reset(factory->CreateTablePropertiesCollector(context));
83
109
      const int kSample = 10;
84
1.30k
      for (int delete_rate = 0; delete_rate <= kSample; ++delete_rate) {
85
1.19k
        int deletions = 0;
86
56.9M
        for (int i = 0; i < kPaddedWindowSize; ++i) {
87
56.9M
          if (i % kSample < delete_rate) {
88
28.4M
            CHECK_OK(collector->AddUserKey(
89
28.4M
                "hello", "rocksdb", rocksdb::kEntryDelete, 0, 0));
90
28.4M
            deletions++;
91
28.4M
          } else {
92
28.4M
            CHECK_OK(collector->AddUserKey(
93
28.4M
                "hello", "rocksdb", rocksdb::kEntryPut, 0, 0));
94
28.4M
          }
95
56.9M
        }
96
1.19k
        if (collector->NeedCompact() !=
97
1.19k
            (deletions >= kNumDeletionTrigger) &&
98
0
            std::abs(deletions - kNumDeletionTrigger) > kBias) {
99
0
          fprintf(stderr, "[Error] collector->NeedCompact() != (%d >= %d)"
100
0
                  " with kWindowSize = %d and kNumDeletionTrigger = %d\n",
101
0
                  deletions, kNumDeletionTrigger,
102
0
                  kWindowSize, kNumDeletionTrigger);
103
0
          assert(false);
104
0
        }
105
1.19k
        CHECK_OK(collector->Finish(nullptr));
106
1.19k
      }
107
109
    }
108
109
    // Only one section of a file satisfies the compaction trigger
110
109
    LOG_TIMING(INFO, "TEST2") {
111
109
      std::unique_ptr<rocksdb::TablePropertiesCollector> collector;
112
109
      auto factory = rocksdb::NewCompactOnDeletionCollectorFactory(
113
109
          kWindowSize, kNumDeletionTrigger);
114
109
      collector.reset(factory->CreateTablePropertiesCollector(context));
115
109
      const int kSample = 10;
116
1.30k
      for (int delete_rate = 0; delete_rate <= kSample; ++delete_rate) {
117
1.19k
        int deletions = 0;
118
7.19k
        for (int section = 0; section < 5; ++section) {
119
5.99k
          int initial_entries = rnd.Uniform(kWindowSize) + kWindowSize;
120
427M
          for (int i = 0; i < initial_entries; ++i) {
121
427M
            CHECK_OK(collector->AddUserKey(
122
427M
                "hello", "rocksdb", rocksdb::kEntryPut, 0, 0));
123
427M
          }
124
5.99k
        }
125
56.9M
        for (int i = 0; i < kPaddedWindowSize; ++i) {
126
56.9M
          if (i % kSample < delete_rate) {
127
28.4M
            CHECK_OK(collector->AddUserKey(
128
28.4M
                "hello", "rocksdb", rocksdb::kEntryDelete, 0, 0));
129
28.4M
            deletions++;
130
28.4M
          } else {
131
28.4M
            CHECK_OK(collector->AddUserKey(
132
28.4M
                "hello", "rocksdb", rocksdb::kEntryPut, 0, 0));
133
28.4M
          }
134
56.9M
        }
135
7.19k
        for (int section = 0; section < 5; ++section) {
136
5.99k
          int ending_entries = rnd.Uniform(kWindowSize) + kWindowSize;
137
426M
          for (int i = 0; i < ending_entries; ++i) {
138
426M
            CHECK_OK(collector->AddUserKey(
139
426M
               "hello", "rocksdb", rocksdb::kEntryPut, 0, 0));
140
426M
          }
141
5.99k
        }
142
1.19k
        if (collector->NeedCompact() != (deletions >= kNumDeletionTrigger) &&
143
1
            std::abs(deletions - kNumDeletionTrigger) > kBias) {
144
0
          fprintf(stderr, "[Error] collector->NeedCompact() %d != (%d >= %d)"
145
0
                  " with kWindowSize = %d, kNumDeletionTrigger = %d\n",
146
0
                  collector->NeedCompact(),
147
0
                  deletions, kNumDeletionTrigger, kWindowSize,
148
0
                  kNumDeletionTrigger);
149
0
          assert(false);
150
0
        }
151
1.19k
        CHECK_OK(collector->Finish(nullptr));
152
1.19k
      }
153
109
    }
154
155
    // TEST 3:  Issues a lots of deletes, but their density is not
156
    // high enough to trigger compaction.
157
109
    LOG_TIMING(INFO, "TEST3") {
158
109
      std::unique_ptr<rocksdb::TablePropertiesCollector> collector;
159
109
      auto factory = rocksdb::NewCompactOnDeletionCollectorFactory(
160
109
          kWindowSize, kNumDeletionTrigger);
161
109
      collector.reset(factory->CreateTablePropertiesCollector(context));
162
109
      assert(collector->NeedCompact() == false);
163
      // Insert "kNumDeletionTrigger * 0.95" deletions for every
164
      // "kWindowSize" and verify compaction is not needed.
165
109
      const int kDeletionsPerSection = kNumDeletionTrigger * 95 / 100;
166
109
      if (kDeletionsPerSection >= 0) {
167
21.9k
        for (int section = 0; section < 200; ++section) {
168
1.03G
          for (int i = 0; i < kPaddedWindowSize; ++i) {
169
1.03G
            if (i < kDeletionsPerSection) {
170
513M
              CHECK_OK(collector->AddUserKey(
171
513M
                  "hello", "rocksdb", rocksdb::kEntryDelete, 0, 0));
172
521M
            } else {
173
521M
              CHECK_OK(collector->AddUserKey(
174
521M
                  "hello", "rocksdb", rocksdb::kEntryPut, 0, 0));
175
521M
            }
176
1.03G
          }
177
21.8k
        }
178
109
        if (collector->NeedCompact() &&
179
0
            std::abs(kDeletionsPerSection - kNumDeletionTrigger) > kBias) {
180
0
          fprintf(stderr, "[Error] collector->NeedCompact() != false"
181
0
                  " with kWindowSize = %d and kNumDeletionTrigger = %d\n",
182
0
                  kWindowSize, kNumDeletionTrigger);
183
0
          assert(false);
184
0
        }
185
109
        CHECK_OK(collector->Finish(nullptr));
186
109
      }
187
109
    }
188
109
  }
189
1
  fprintf(stderr, "PASSED\n");
190
1
}
191
#else
192
int main(int argc, char** argv) {
193
  fprintf(stderr, "SKIPPED as RocksDBLite does not include utilities.\n");
194
  return 0;
195
}
196
#endif  // !ROCKSDB_LITE