]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/memory/memory_allocator_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / memory / memory_allocator_test.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // Copyright (c) 2019 Intel Corporation
3 // This source code is licensed under both the GPLv2 (found in the
4 // COPYING file in the root directory) and Apache 2.0 License
5 // (found in the LICENSE.Apache file in the root directory).
6
7 #include <cstdio>
8
9 #include "memory/jemalloc_nodump_allocator.h"
10 #include "memory/memkind_kmem_allocator.h"
11 #include "rocksdb/cache.h"
12 #include "rocksdb/convenience.h"
13 #include "rocksdb/db.h"
14 #include "rocksdb/options.h"
15 #include "table/block_based/block_based_table_factory.h"
16 #include "test_util/testharness.h"
17 #include "utilities/memory_allocators.h"
18
19 namespace ROCKSDB_NAMESPACE {
20
21 // TODO: the tests do not work in LITE mode due to relying on
22 // `CreateFromString()` to create non-default memory allocators.
23 #ifndef ROCKSDB_LITE
24
25 class MemoryAllocatorTest
26 : public testing::Test,
27 public ::testing::WithParamInterface<std::tuple<std::string, bool>> {
28 public:
29 MemoryAllocatorTest() {
30 std::tie(id_, supported_) = GetParam();
31 Status s =
32 MemoryAllocator::CreateFromString(ConfigOptions(), id_, &allocator_);
33 EXPECT_EQ(supported_, s.ok());
34 }
35 bool IsSupported() { return supported_; }
36
37 std::shared_ptr<MemoryAllocator> allocator_;
38 std::string id_;
39
40 private:
41 bool supported_;
42 };
43
44 TEST_P(MemoryAllocatorTest, Allocate) {
45 if (!IsSupported()) {
46 return;
47 }
48 void* p = allocator_->Allocate(1024);
49 ASSERT_NE(p, nullptr);
50 size_t size = allocator_->UsableSize(p, 1024);
51 ASSERT_GE(size, 1024);
52 allocator_->Deallocate(p);
53 }
54
55 TEST_P(MemoryAllocatorTest, CreateAllocator) {
56 ConfigOptions config_options;
57 config_options.ignore_unknown_options = false;
58 config_options.ignore_unsupported_options = false;
59 std::shared_ptr<MemoryAllocator> orig, copy;
60 Status s = MemoryAllocator::CreateFromString(config_options, id_, &orig);
61 if (!IsSupported()) {
62 ASSERT_TRUE(s.IsNotSupported());
63 } else {
64 ASSERT_OK(s);
65 ASSERT_NE(orig, nullptr);
66 #ifndef ROCKSDB_LITE
67 std::string str = orig->ToString(config_options);
68 ASSERT_OK(MemoryAllocator::CreateFromString(config_options, str, &copy));
69 ASSERT_EQ(orig, copy);
70 #endif // ROCKSDB_LITE
71 }
72 }
73
74 TEST_P(MemoryAllocatorTest, DatabaseBlockCache) {
75 if (!IsSupported()) {
76 // Check if a memory node is available for allocation
77 }
78
79 // Create database with block cache using the MemoryAllocator
80 Options options;
81 std::string dbname = test::PerThreadDBPath("allocator_test");
82 ASSERT_OK(DestroyDB(dbname, options));
83
84 options.create_if_missing = true;
85 BlockBasedTableOptions table_options;
86 auto cache = NewLRUCache(1024 * 1024, 6, false, 0.0, allocator_);
87 table_options.block_cache = cache;
88 options.table_factory.reset(NewBlockBasedTableFactory(table_options));
89 DB* db = nullptr;
90 Status s = DB::Open(options, dbname, &db);
91 ASSERT_OK(s);
92 ASSERT_NE(db, nullptr);
93 ASSERT_LE(cache->GetUsage(), 104); // Cache will contain stats
94
95 // Write 2kB (200 values, each 10 bytes)
96 int num_keys = 200;
97 WriteOptions wo;
98 std::string val = "0123456789";
99 for (int i = 0; i < num_keys; i++) {
100 std::string key = std::to_string(i);
101 s = db->Put(wo, Slice(key), Slice(val));
102 ASSERT_OK(s);
103 }
104 ASSERT_OK(db->Flush(FlushOptions())); // Flush all data from memtable so that
105 // reads are from block cache
106
107 // Read and check block cache usage
108 ReadOptions ro;
109 std::string result;
110 for (int i = 0; i < num_keys; i++) {
111 std::string key = std::to_string(i);
112 s = db->Get(ro, key, &result);
113 ASSERT_OK(s);
114 ASSERT_EQ(result, val);
115 }
116 ASSERT_GT(cache->GetUsage(), 2000);
117
118 // Close database
119 s = db->Close();
120 ASSERT_OK(s);
121 delete db;
122 ASSERT_OK(DestroyDB(dbname, options));
123 }
124
125 class CreateMemoryAllocatorTest : public testing::Test {
126 public:
127 CreateMemoryAllocatorTest() {
128 config_options_.ignore_unknown_options = false;
129 config_options_.ignore_unsupported_options = false;
130 }
131 ConfigOptions config_options_;
132 };
133
134 TEST_F(CreateMemoryAllocatorTest, JemallocOptionsTest) {
135 std::shared_ptr<MemoryAllocator> allocator;
136 std::string id = std::string("id=") + JemallocNodumpAllocator::kClassName();
137 Status s = MemoryAllocator::CreateFromString(config_options_, id, &allocator);
138 if (!JemallocNodumpAllocator::IsSupported()) {
139 ASSERT_NOK(s);
140 ROCKSDB_GTEST_BYPASS("JEMALLOC not supported");
141 return;
142 }
143 ASSERT_OK(s);
144 ASSERT_NE(allocator, nullptr);
145 JemallocAllocatorOptions jopts;
146 auto opts = allocator->GetOptions<JemallocAllocatorOptions>();
147 ASSERT_NE(opts, nullptr);
148 ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
149 ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
150 ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
151
152 ASSERT_NOK(MemoryAllocator::CreateFromString(
153 config_options_,
154 id + "; limit_tcache_size=true; tcache_size_lower_bound=4096; "
155 "tcache_size_upper_bound=1024",
156 &allocator));
157 ASSERT_OK(MemoryAllocator::CreateFromString(
158 config_options_,
159 id + "; limit_tcache_size=false; tcache_size_lower_bound=4096; "
160 "tcache_size_upper_bound=1024",
161 &allocator));
162 opts = allocator->GetOptions<JemallocAllocatorOptions>();
163 ASSERT_NE(opts, nullptr);
164 ASSERT_EQ(opts->limit_tcache_size, false);
165 ASSERT_EQ(opts->tcache_size_lower_bound, 4096U);
166 ASSERT_EQ(opts->tcache_size_upper_bound, 1024U);
167 ASSERT_OK(MemoryAllocator::CreateFromString(
168 config_options_,
169 id + "; limit_tcache_size=true; tcache_size_upper_bound=4096; "
170 "tcache_size_lower_bound=1024",
171 &allocator));
172 opts = allocator->GetOptions<JemallocAllocatorOptions>();
173 ASSERT_NE(opts, nullptr);
174 ASSERT_EQ(opts->limit_tcache_size, true);
175 ASSERT_EQ(opts->tcache_size_lower_bound, 1024U);
176 ASSERT_EQ(opts->tcache_size_upper_bound, 4096U);
177 }
178
179 TEST_F(CreateMemoryAllocatorTest, NewJemallocNodumpAllocator) {
180 JemallocAllocatorOptions jopts;
181 std::shared_ptr<MemoryAllocator> allocator;
182
183 jopts.limit_tcache_size = true;
184 jopts.tcache_size_lower_bound = 2 * 1024;
185 jopts.tcache_size_upper_bound = 1024;
186
187 ASSERT_NOK(NewJemallocNodumpAllocator(jopts, nullptr));
188 Status s = NewJemallocNodumpAllocator(jopts, &allocator);
189 std::string msg;
190 if (!JemallocNodumpAllocator::IsSupported(&msg)) {
191 ASSERT_NOK(s);
192 ROCKSDB_GTEST_BYPASS("JEMALLOC not supported");
193 return;
194 }
195 ASSERT_NOK(s); // Invalid options
196 ASSERT_EQ(allocator, nullptr);
197
198 jopts.tcache_size_upper_bound = 4 * 1024;
199 ASSERT_OK(NewJemallocNodumpAllocator(jopts, &allocator));
200 ASSERT_NE(allocator, nullptr);
201 auto opts = allocator->GetOptions<JemallocAllocatorOptions>();
202 ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
203 ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
204 ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
205
206 jopts.limit_tcache_size = false;
207 ASSERT_OK(NewJemallocNodumpAllocator(jopts, &allocator));
208 ASSERT_NE(allocator, nullptr);
209 opts = allocator->GetOptions<JemallocAllocatorOptions>();
210 ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
211 ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
212 ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
213 }
214
215 INSTANTIATE_TEST_CASE_P(DefaultMemoryAllocator, MemoryAllocatorTest,
216 ::testing::Values(std::make_tuple(
217 DefaultMemoryAllocator::kClassName(), true)));
218 #ifdef MEMKIND
219 INSTANTIATE_TEST_CASE_P(
220 MemkindkMemAllocator, MemoryAllocatorTest,
221 ::testing::Values(std::make_tuple(MemkindKmemAllocator::kClassName(),
222 MemkindKmemAllocator::IsSupported())));
223 #endif // MEMKIND
224
225 #ifdef ROCKSDB_JEMALLOC
226 INSTANTIATE_TEST_CASE_P(
227 JemallocNodumpAllocator, MemoryAllocatorTest,
228 ::testing::Values(std::make_tuple(JemallocNodumpAllocator::kClassName(),
229 JemallocNodumpAllocator::IsSupported())));
230 #endif // ROCKSDB_JEMALLOC
231
232 #endif // ROCKSDB_LITE
233
234 } // namespace ROCKSDB_NAMESPACE
235
236 int main(int argc, char** argv) {
237 ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
238 ::testing::InitGoogleTest(&argc, argv);
239 return RUN_ALL_TESTS();
240 }