| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
- // Copyright (c) 2019 Intel Corporation
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- #include <cstdio>
- #include "memory/jemalloc_nodump_allocator.h"
- #include "memory/memkind_kmem_allocator.h"
- #include "rocksdb/cache.h"
- #include "rocksdb/convenience.h"
- #include "rocksdb/db.h"
- #include "rocksdb/options.h"
- #include "table/block_based/block_based_table_factory.h"
- #include "test_util/testharness.h"
- #include "utilities/memory_allocators.h"
- namespace ROCKSDB_NAMESPACE {
- // TODO: the tests do not work in LITE mode due to relying on
- // `CreateFromString()` to create non-default memory allocators.
- class MemoryAllocatorTest
- : public testing::Test,
- public ::testing::WithParamInterface<std::tuple<std::string, bool>> {
- public:
- MemoryAllocatorTest() {
- std::tie(id_, supported_) = GetParam();
- Status s =
- MemoryAllocator::CreateFromString(ConfigOptions(), id_, &allocator_);
- EXPECT_EQ(supported_, s.ok());
- }
- bool IsSupported() { return supported_; }
- std::shared_ptr<MemoryAllocator> allocator_;
- std::string id_;
- private:
- bool supported_;
- };
- TEST_P(MemoryAllocatorTest, Allocate) {
- if (!IsSupported()) {
- return;
- }
- void* p = allocator_->Allocate(1024);
- ASSERT_NE(p, nullptr);
- size_t size = allocator_->UsableSize(p, 1024);
- ASSERT_GE(size, 1024);
- allocator_->Deallocate(p);
- }
- TEST_P(MemoryAllocatorTest, CreateAllocator) {
- ConfigOptions config_options;
- config_options.ignore_unknown_options = false;
- config_options.ignore_unsupported_options = false;
- std::shared_ptr<MemoryAllocator> orig, copy;
- Status s = MemoryAllocator::CreateFromString(config_options, id_, &orig);
- if (!IsSupported()) {
- ASSERT_TRUE(s.IsNotSupported());
- } else {
- ASSERT_OK(s);
- ASSERT_NE(orig, nullptr);
- std::string str = orig->ToString(config_options);
- ASSERT_OK(MemoryAllocator::CreateFromString(config_options, str, ©));
- ASSERT_EQ(orig, copy);
- }
- }
- TEST_P(MemoryAllocatorTest, DatabaseBlockCache) {
- if (!IsSupported()) {
- // Check if a memory node is available for allocation
- }
- // Create database with block cache using the MemoryAllocator
- Options options;
- std::string dbname = test::PerThreadDBPath("allocator_test");
- ASSERT_OK(DestroyDB(dbname, options));
- options.create_if_missing = true;
- BlockBasedTableOptions table_options;
- auto cache = NewLRUCache(1024 * 1024, 6, false, 0.0, allocator_);
- table_options.block_cache = cache;
- options.table_factory.reset(NewBlockBasedTableFactory(table_options));
- DB* db = nullptr;
- Status s = DB::Open(options, dbname, &db);
- ASSERT_OK(s);
- ASSERT_NE(db, nullptr);
- ASSERT_LE(cache->GetUsage(), 104); // Cache will contain stats
- // Write 2kB (200 values, each 10 bytes)
- int num_keys = 200;
- WriteOptions wo;
- std::string val = "0123456789";
- for (int i = 0; i < num_keys; i++) {
- std::string key = std::to_string(i);
- s = db->Put(wo, Slice(key), Slice(val));
- ASSERT_OK(s);
- }
- ASSERT_OK(db->Flush(FlushOptions())); // Flush all data from memtable so that
- // reads are from block cache
- // Read and check block cache usage
- ReadOptions ro;
- std::string result;
- for (int i = 0; i < num_keys; i++) {
- std::string key = std::to_string(i);
- s = db->Get(ro, key, &result);
- ASSERT_OK(s);
- ASSERT_EQ(result, val);
- }
- ASSERT_GT(cache->GetUsage(), 2000);
- // Close database
- s = db->Close();
- ASSERT_OK(s);
- delete db;
- ASSERT_OK(DestroyDB(dbname, options));
- }
- class CreateMemoryAllocatorTest : public testing::Test {
- public:
- CreateMemoryAllocatorTest() {
- config_options_.ignore_unknown_options = false;
- config_options_.ignore_unsupported_options = false;
- }
- ConfigOptions config_options_;
- };
- TEST_F(CreateMemoryAllocatorTest, JemallocOptionsTest) {
- std::shared_ptr<MemoryAllocator> allocator;
- std::string id = std::string("id=") + JemallocNodumpAllocator::kClassName();
- Status s = MemoryAllocator::CreateFromString(config_options_, id, &allocator);
- if (!JemallocNodumpAllocator::IsSupported()) {
- ASSERT_NOK(s);
- ROCKSDB_GTEST_BYPASS("JEMALLOC not supported");
- return;
- }
- ASSERT_OK(s);
- ASSERT_NE(allocator, nullptr);
- JemallocAllocatorOptions jopts;
- auto opts = allocator->GetOptions<JemallocAllocatorOptions>();
- ASSERT_NE(opts, nullptr);
- ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
- ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
- ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
- ASSERT_NOK(MemoryAllocator::CreateFromString(
- config_options_,
- id + "; limit_tcache_size=true; tcache_size_lower_bound=4096; "
- "tcache_size_upper_bound=1024",
- &allocator));
- ASSERT_OK(MemoryAllocator::CreateFromString(
- config_options_,
- id + "; limit_tcache_size=false; tcache_size_lower_bound=4096; "
- "tcache_size_upper_bound=1024",
- &allocator));
- opts = allocator->GetOptions<JemallocAllocatorOptions>();
- ASSERT_NE(opts, nullptr);
- ASSERT_EQ(opts->limit_tcache_size, false);
- ASSERT_EQ(opts->tcache_size_lower_bound, 4096U);
- ASSERT_EQ(opts->tcache_size_upper_bound, 1024U);
- ASSERT_OK(MemoryAllocator::CreateFromString(
- config_options_,
- id + "; limit_tcache_size=true; tcache_size_upper_bound=4096; "
- "tcache_size_lower_bound=1024",
- &allocator));
- opts = allocator->GetOptions<JemallocAllocatorOptions>();
- ASSERT_NE(opts, nullptr);
- ASSERT_EQ(opts->limit_tcache_size, true);
- ASSERT_EQ(opts->tcache_size_lower_bound, 1024U);
- ASSERT_EQ(opts->tcache_size_upper_bound, 4096U);
- }
- TEST_F(CreateMemoryAllocatorTest, NewJemallocNodumpAllocator) {
- JemallocAllocatorOptions jopts;
- std::shared_ptr<MemoryAllocator> allocator;
- jopts.limit_tcache_size = true;
- jopts.tcache_size_lower_bound = 2 * 1024;
- jopts.tcache_size_upper_bound = 1024;
- ASSERT_NOK(NewJemallocNodumpAllocator(jopts, nullptr));
- Status s = NewJemallocNodumpAllocator(jopts, &allocator);
- std::string msg;
- if (!JemallocNodumpAllocator::IsSupported(&msg)) {
- ASSERT_NOK(s);
- ROCKSDB_GTEST_BYPASS("JEMALLOC not supported");
- return;
- }
- ASSERT_NOK(s); // Invalid options
- ASSERT_EQ(allocator, nullptr);
- jopts.tcache_size_upper_bound = 4 * 1024;
- ASSERT_OK(NewJemallocNodumpAllocator(jopts, &allocator));
- ASSERT_NE(allocator, nullptr);
- auto opts = allocator->GetOptions<JemallocAllocatorOptions>();
- ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
- ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
- ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
- jopts.limit_tcache_size = false;
- ASSERT_OK(NewJemallocNodumpAllocator(jopts, &allocator));
- ASSERT_NE(allocator, nullptr);
- opts = allocator->GetOptions<JemallocAllocatorOptions>();
- ASSERT_EQ(opts->tcache_size_upper_bound, jopts.tcache_size_upper_bound);
- ASSERT_EQ(opts->tcache_size_lower_bound, jopts.tcache_size_lower_bound);
- ASSERT_EQ(opts->limit_tcache_size, jopts.limit_tcache_size);
- }
- INSTANTIATE_TEST_CASE_P(DefaultMemoryAllocator, MemoryAllocatorTest,
- ::testing::Values(std::make_tuple(
- DefaultMemoryAllocator::kClassName(), true)));
- #ifdef MEMKIND
- INSTANTIATE_TEST_CASE_P(
- MemkindkMemAllocator, MemoryAllocatorTest,
- ::testing::Values(std::make_tuple(MemkindKmemAllocator::kClassName(),
- MemkindKmemAllocator::IsSupported())));
- #endif // MEMKIND
- #ifdef ROCKSDB_JEMALLOC
- INSTANTIATE_TEST_CASE_P(
- JemallocNodumpAllocator, MemoryAllocatorTest,
- ::testing::Values(std::make_tuple(JemallocNodumpAllocator::kClassName(),
- JemallocNodumpAllocator::IsSupported())));
- #endif // ROCKSDB_JEMALLOC
- } // namespace ROCKSDB_NAMESPACE
- int main(int argc, char** argv) {
- ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
- }
|