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.
6 #include "rocksdb/utilities/sim_cache.h"
8 #include "db/db_test_util.h"
9 #include "port/stack_trace.h"
13 class SimCacheTest
: public DBTestBase
{
15 size_t miss_count_
= 0;
16 size_t hit_count_
= 0;
17 size_t insert_count_
= 0;
18 size_t failure_count_
= 0;
21 const size_t kNumBlocks
= 5;
22 const size_t kValueSize
= 1000;
24 SimCacheTest() : DBTestBase("/sim_cache_test") {}
26 BlockBasedTableOptions
GetTableOptions() {
27 BlockBasedTableOptions table_options
;
28 // Set a small enough block size so that each key-value get its own block.
29 table_options
.block_size
= 1;
33 Options
GetOptions(const BlockBasedTableOptions
& table_options
) {
34 Options options
= CurrentOptions();
35 options
.create_if_missing
= true;
36 // options.compression = kNoCompression;
37 options
.statistics
= rocksdb::CreateDBStatistics();
38 options
.table_factory
.reset(new BlockBasedTableFactory(table_options
));
42 void InitTable(const Options
& options
) {
43 std::string
value(kValueSize
, 'a');
44 for (size_t i
= 0; i
< kNumBlocks
* 2; i
++) {
45 ASSERT_OK(Put(ToString(i
), value
.c_str()));
49 void RecordCacheCounters(const Options
& options
) {
50 miss_count_
= TestGetTickerCount(options
, BLOCK_CACHE_MISS
);
51 hit_count_
= TestGetTickerCount(options
, BLOCK_CACHE_HIT
);
52 insert_count_
= TestGetTickerCount(options
, BLOCK_CACHE_ADD
);
53 failure_count_
= TestGetTickerCount(options
, BLOCK_CACHE_ADD_FAILURES
);
56 void CheckCacheCounters(const Options
& options
, size_t expected_misses
,
57 size_t expected_hits
, size_t expected_inserts
,
58 size_t expected_failures
) {
59 size_t new_miss_count
= TestGetTickerCount(options
, BLOCK_CACHE_MISS
);
60 size_t new_hit_count
= TestGetTickerCount(options
, BLOCK_CACHE_HIT
);
61 size_t new_insert_count
= TestGetTickerCount(options
, BLOCK_CACHE_ADD
);
62 size_t new_failure_count
=
63 TestGetTickerCount(options
, BLOCK_CACHE_ADD_FAILURES
);
64 ASSERT_EQ(miss_count_
+ expected_misses
, new_miss_count
);
65 ASSERT_EQ(hit_count_
+ expected_hits
, new_hit_count
);
66 ASSERT_EQ(insert_count_
+ expected_inserts
, new_insert_count
);
67 ASSERT_EQ(failure_count_
+ expected_failures
, new_failure_count
);
68 miss_count_
= new_miss_count
;
69 hit_count_
= new_hit_count
;
70 insert_count_
= new_insert_count
;
71 failure_count_
= new_failure_count
;
75 TEST_F(SimCacheTest
, SimCache
) {
76 ReadOptions read_options
;
77 auto table_options
= GetTableOptions();
78 auto options
= GetOptions(table_options
);
80 std::shared_ptr
<SimCache
> simCache
=
81 NewSimCache(NewLRUCache(0, 0, false), 20000, 0);
82 table_options
.block_cache
= simCache
;
83 options
.table_factory
.reset(new BlockBasedTableFactory(table_options
));
85 RecordCacheCounters(options
);
87 std::vector
<std::unique_ptr
<Iterator
>> iterators(kNumBlocks
);
88 Iterator
* iter
= nullptr;
90 // Load blocks into cache.
91 for (size_t i
= 0; i
< kNumBlocks
; i
++) {
92 iter
= db_
->NewIterator(read_options
);
93 iter
->Seek(ToString(i
));
94 ASSERT_OK(iter
->status());
95 CheckCacheCounters(options
, 1, 0, 1, 0);
96 iterators
[i
].reset(iter
);
99 simCache
->get_hit_counter() + simCache
->get_miss_counter());
100 ASSERT_EQ(0, simCache
->get_hit_counter());
101 size_t usage
= simCache
->GetUsage();
103 ASSERT_EQ(usage
, simCache
->GetSimUsage());
104 simCache
->SetCapacity(usage
);
105 ASSERT_EQ(usage
, simCache
->GetPinnedUsage());
107 // Test with strict capacity limit.
108 simCache
->SetStrictCapacityLimit(true);
109 iter
= db_
->NewIterator(read_options
);
110 iter
->Seek(ToString(kNumBlocks
* 2 - 1));
111 ASSERT_TRUE(iter
->status().IsIncomplete());
112 CheckCacheCounters(options
, 1, 0, 0, 1);
116 // Release iterators and access cache again.
117 for (size_t i
= 0; i
< kNumBlocks
; i
++) {
118 iterators
[i
].reset();
119 CheckCacheCounters(options
, 0, 0, 0, 0);
121 // Add kNumBlocks again
122 for (size_t i
= 0; i
< kNumBlocks
; i
++) {
123 std::unique_ptr
<Iterator
> it(db_
->NewIterator(read_options
));
124 it
->Seek(ToString(i
));
125 ASSERT_OK(it
->status());
126 CheckCacheCounters(options
, 0, 1, 0, 0);
128 ASSERT_EQ(5, simCache
->get_hit_counter());
129 for (size_t i
= kNumBlocks
; i
< kNumBlocks
* 2; i
++) {
130 std::unique_ptr
<Iterator
> it(db_
->NewIterator(read_options
));
131 it
->Seek(ToString(i
));
132 ASSERT_OK(it
->status());
133 CheckCacheCounters(options
, 1, 0, 1, 0);
135 ASSERT_EQ(0, simCache
->GetPinnedUsage());
136 ASSERT_EQ(3 * kNumBlocks
+ 1,
137 simCache
->get_hit_counter() + simCache
->get_miss_counter());
138 ASSERT_EQ(6, simCache
->get_hit_counter());
141 } // namespace rocksdb
143 int main(int argc
, char** argv
) {
144 rocksdb::port::InstallStackTraceHandler();
145 ::testing::InitGoogleTest(&argc
, argv
);
146 return RUN_ALL_TESTS();