[Optimize][Cache]Implementation of Separated Page Cache (#5008)
#4995 **Implementation of Separated Page Cache** - Add config "index_page_cache_ratio" to set the ratio of capacity of index page cache - Change the member of StoragePageCache to maintain two type of cache - Change the interface of StoragePageCache for selecting type of cache - Change the usage of page cache in read_and_decompress_page in page_io.cpp - add page type as argument - check if current page type is available in StoragePageCache (cover the situation of ratio == 0 or 1) - Add type as argument in superior call of read_and_decompress_page - Change Unit Test
This commit is contained in:
@ -260,6 +260,9 @@ CONF_Int64(index_stream_cache_capacity, "10737418240");
|
||||
|
||||
// Cache for storage page size
|
||||
CONF_String(storage_page_cache_limit, "20%");
|
||||
// Percentage for index page cache
|
||||
// all storage page cache will be divided into data_page_cache and index_page_cache
|
||||
CONF_Int32(index_page_cache_percentage, "10");
|
||||
// whether to disable page cache feature in storage
|
||||
CONF_Bool(disable_storage_page_cache, "false");
|
||||
|
||||
|
||||
@ -21,26 +21,38 @@ namespace doris {
|
||||
|
||||
StoragePageCache* StoragePageCache::_s_instance = nullptr;
|
||||
|
||||
void StoragePageCache::create_global_cache(size_t capacity) {
|
||||
void StoragePageCache::create_global_cache(size_t capacity, int32_t index_cache_percentage) {
|
||||
DCHECK(_s_instance == nullptr);
|
||||
static StoragePageCache instance(capacity);
|
||||
static StoragePageCache instance(capacity, index_cache_percentage);
|
||||
_s_instance = &instance;
|
||||
}
|
||||
|
||||
StoragePageCache::StoragePageCache(size_t capacity)
|
||||
: _cache(new_lru_cache("StoragePageCache", capacity)) {}
|
||||
StoragePageCache::StoragePageCache(size_t capacity, int32_t index_cache_percentage)
|
||||
: _index_cache_percentage(index_cache_percentage) {
|
||||
if (index_cache_percentage == 0) {
|
||||
_data_page_cache = std::unique_ptr<Cache>(new_lru_cache("DataPageCache", capacity));
|
||||
} else if (index_cache_percentage == 100) {
|
||||
_index_page_cache = std::unique_ptr<Cache>(new_lru_cache("IndexPageCache", capacity));
|
||||
} else if (index_cache_percentage > 0 && index_cache_percentage < 100) {
|
||||
_data_page_cache = std::unique_ptr<Cache>(new_lru_cache("DataPageCache", capacity * (100 - index_cache_percentage) / 100));
|
||||
_index_page_cache = std::unique_ptr<Cache>(new_lru_cache("IndexPageCache", capacity * index_cache_percentage / 100));
|
||||
} else {
|
||||
CHECK(false) << "invalid index page cache percentage";
|
||||
}
|
||||
}
|
||||
|
||||
bool StoragePageCache::lookup(const CacheKey& key, PageCacheHandle* handle) {
|
||||
auto lru_handle = _cache->lookup(key.encode());
|
||||
bool StoragePageCache::lookup(const CacheKey& key, PageCacheHandle* handle, segment_v2::PageTypePB page_type) {
|
||||
auto cache = _get_page_cache(page_type);
|
||||
auto lru_handle = cache->lookup(key.encode());
|
||||
if (lru_handle == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*handle = PageCacheHandle(_cache.get(), lru_handle);
|
||||
*handle = PageCacheHandle(cache, lru_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StoragePageCache::insert(const CacheKey& key, const Slice& data, PageCacheHandle* handle,
|
||||
bool in_memory) {
|
||||
segment_v2::PageTypePB page_type, bool in_memory) {
|
||||
auto deleter = [](const doris::CacheKey& key, void* value) { delete[](uint8_t*) value; };
|
||||
|
||||
CachePriority priority = CachePriority::NORMAL;
|
||||
@ -48,8 +60,9 @@ void StoragePageCache::insert(const CacheKey& key, const Slice& data, PageCacheH
|
||||
priority = CachePriority::DURABLE;
|
||||
}
|
||||
|
||||
auto lru_handle = _cache->insert(key.encode(), data.data, data.size, deleter, priority);
|
||||
*handle = PageCacheHandle(_cache.get(), lru_handle);
|
||||
auto cache = _get_page_cache(page_type);
|
||||
auto lru_handle = cache->insert(key.encode(), data.data, data.size, deleter, priority);
|
||||
*handle = PageCacheHandle(cache, lru_handle);
|
||||
}
|
||||
|
||||
} // namespace doris
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
#include "gutil/macros.h" // for DISALLOW_COPY_AND_ASSIGN
|
||||
#include "olap/lru_cache.h"
|
||||
#include "gen_cpp/segment_v2.pb.h" // for cache allocation
|
||||
|
||||
namespace doris {
|
||||
|
||||
@ -53,13 +54,13 @@ public:
|
||||
};
|
||||
|
||||
// Create global instance of this class
|
||||
static void create_global_cache(size_t capacity);
|
||||
static void create_global_cache(size_t capacity, int32_t index_cache_percentage);
|
||||
|
||||
// Return global instance.
|
||||
// Client should call create_global_cache before.
|
||||
static StoragePageCache* instance() { return _s_instance; }
|
||||
|
||||
StoragePageCache(size_t capacity);
|
||||
StoragePageCache(size_t capacity, int32_t index_cache_percentage);
|
||||
|
||||
// Lookup the given page in the cache.
|
||||
//
|
||||
@ -67,8 +68,10 @@ public:
|
||||
// PageCacheHandle will release cache entry to cache when it
|
||||
// destructs.
|
||||
//
|
||||
// Cache type selection is determined by page_type argument
|
||||
//
|
||||
// Return true if entry is found, otherwise return false.
|
||||
bool lookup(const CacheKey& key, PageCacheHandle* handle);
|
||||
bool lookup(const CacheKey& key, PageCacheHandle* handle, segment_v2::PageTypePB page_type);
|
||||
|
||||
// Insert a page with key into this cache.
|
||||
// Given handle will be set to valid reference.
|
||||
@ -76,13 +79,33 @@ public:
|
||||
// concurrently, this function can assure that only one page is cached.
|
||||
// The in_memory page will have higher priority.
|
||||
void insert(const CacheKey& key, const Slice& data, PageCacheHandle* handle,
|
||||
bool in_memory = false);
|
||||
segment_v2::PageTypePB page_type, bool in_memory = false);
|
||||
|
||||
// Page cache available check.
|
||||
// When percentage is set to 0 or 100, the index or data cache will not be allocated.
|
||||
bool is_cache_available(segment_v2::PageTypePB page_type) {
|
||||
return _get_page_cache(page_type) != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
StoragePageCache();
|
||||
static StoragePageCache* _s_instance;
|
||||
|
||||
std::unique_ptr<Cache> _cache = nullptr;
|
||||
int32_t _index_cache_percentage = 0;
|
||||
std::unique_ptr<Cache> _data_page_cache = nullptr;
|
||||
std::unique_ptr<Cache> _index_page_cache = nullptr;
|
||||
|
||||
Cache* _get_page_cache(segment_v2::PageTypePB page_type) {
|
||||
switch (page_type)
|
||||
{
|
||||
case segment_v2::DATA_PAGE:
|
||||
return _data_page_cache.get();
|
||||
case segment_v2::INDEX_PAGE:
|
||||
return _index_page_cache.get();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// A handle for StoragePageCache entry. This class make it easy to handle
|
||||
|
||||
@ -130,6 +130,7 @@ Status ColumnReader::read_page(const ColumnIteratorOptions& iter_opts, const Pag
|
||||
opts.verify_checksum = _opts.verify_checksum;
|
||||
opts.use_page_cache = iter_opts.use_page_cache;
|
||||
opts.kept_in_memory = _opts.kept_in_memory;
|
||||
opts.type = iter_opts.type;
|
||||
|
||||
return PageIO::read_and_decompress_page(opts, handle, page_body, footer);
|
||||
}
|
||||
@ -569,6 +570,7 @@ Status FileColumnIterator::_read_data_page(const OrdinalPageIndexIterator& iter)
|
||||
PageHandle handle;
|
||||
Slice page_body;
|
||||
PageFooterPB footer;
|
||||
_opts.type = DATA_PAGE;
|
||||
RETURN_IF_ERROR(_reader->read_page(_opts, iter.page(), &handle, &page_body, &footer));
|
||||
// parse data page
|
||||
RETURN_IF_ERROR(ParsedPage::create(std::move(handle), page_body, footer.data_page_footer(),
|
||||
@ -587,6 +589,7 @@ Status FileColumnIterator::_read_data_page(const OrdinalPageIndexIterator& iter)
|
||||
// read dictionary page
|
||||
Slice dict_data;
|
||||
PageFooterPB dict_footer;
|
||||
_opts.type = INDEX_PAGE;
|
||||
RETURN_IF_ERROR(_reader->read_page(_opts, _reader->get_dict_page_pointer(),
|
||||
&_dict_page_handle, &dict_data, &dict_footer));
|
||||
// ignore dict_footer.dict_page_footer().encoding() due to only
|
||||
|
||||
@ -67,6 +67,10 @@ struct ColumnIteratorOptions {
|
||||
// reader statistics
|
||||
OlapReaderStatistics* stats = nullptr;
|
||||
bool use_page_cache = false;
|
||||
// for page cache allocation
|
||||
// page types are divided into DATA_PAGE & INDEX_PAGE
|
||||
// INDEX_PAGE including index_page, dict_page and short_key_page
|
||||
PageTypePB type;
|
||||
|
||||
void sanity_check() const {
|
||||
CHECK_NOTNULL(rblock);
|
||||
|
||||
@ -72,13 +72,13 @@ Status IndexedColumnReader::load_index_page(fs::ReadableBlock* rblock, const Pag
|
||||
PageHandle* handle, IndexPageReader* reader) {
|
||||
Slice body;
|
||||
PageFooterPB footer;
|
||||
RETURN_IF_ERROR(read_page(rblock, PagePointer(pp), handle, &body, &footer));
|
||||
RETURN_IF_ERROR(read_page(rblock, PagePointer(pp), handle, &body, &footer, INDEX_PAGE));
|
||||
RETURN_IF_ERROR(reader->parse(body, footer.index_page_footer()));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status IndexedColumnReader::read_page(fs::ReadableBlock* rblock, const PagePointer& pp,
|
||||
PageHandle* handle, Slice* body, PageFooterPB* footer) const {
|
||||
PageHandle* handle, Slice* body, PageFooterPB* footer, PageTypePB type) const {
|
||||
PageReadOptions opts;
|
||||
opts.rblock = rblock;
|
||||
opts.page_pointer = pp;
|
||||
@ -87,6 +87,7 @@ Status IndexedColumnReader::read_page(fs::ReadableBlock* rblock, const PagePoint
|
||||
opts.stats = &tmp_stats;
|
||||
opts.use_page_cache = _use_page_cache;
|
||||
opts.kept_in_memory = _kept_in_memory;
|
||||
opts.type = type;
|
||||
|
||||
return PageIO::read_and_decompress_page(opts, handle, body, footer);
|
||||
}
|
||||
@ -97,7 +98,7 @@ Status IndexedColumnIterator::_read_data_page(const PagePointer& pp) {
|
||||
PageHandle handle;
|
||||
Slice body;
|
||||
PageFooterPB footer;
|
||||
RETURN_IF_ERROR(_reader->read_page(_rblock.get(), pp, &handle, &body, &footer));
|
||||
RETURN_IF_ERROR(_reader->read_page(_rblock.get(), pp, &handle, &body, &footer, DATA_PAGE));
|
||||
// parse data page
|
||||
// note that page_index is not used in IndexedColumnIterator, so we pass 0
|
||||
return ParsedPage::create(std::move(handle), body, footer.data_page_footer(),
|
||||
|
||||
@ -51,7 +51,7 @@ public:
|
||||
|
||||
// read a page specified by `pp' from `file' into `handle'
|
||||
Status read_page(fs::ReadableBlock* rblock, const PagePointer& pp, PageHandle* handle,
|
||||
Slice* body, PageFooterPB* footer) const;
|
||||
Slice* body, PageFooterPB* footer, PageTypePB type) const;
|
||||
|
||||
int64_t num_values() const { return _num_values; }
|
||||
const EncodingInfo* encoding_info() const { return _encoding_info; }
|
||||
|
||||
@ -80,6 +80,7 @@ Status OrdinalIndexReader::load(bool use_page_cache, bool kept_in_memory) {
|
||||
opts.stats = &tmp_stats;
|
||||
opts.use_page_cache = use_page_cache;
|
||||
opts.kept_in_memory = kept_in_memory;
|
||||
opts.type = INDEX_PAGE;
|
||||
|
||||
// read index page
|
||||
PageHandle page_handle;
|
||||
|
||||
@ -112,7 +112,7 @@ Status PageIO::read_and_decompress_page(const PageReadOptions& opts, PageHandle*
|
||||
auto cache = StoragePageCache::instance();
|
||||
PageCacheHandle cache_handle;
|
||||
StoragePageCache::CacheKey cache_key(opts.rblock->path(), opts.page_pointer.offset);
|
||||
if (opts.use_page_cache && cache->lookup(cache_key, &cache_handle)) {
|
||||
if (opts.use_page_cache && cache->is_cache_available(opts.type) && cache->lookup(cache_key, &cache_handle, opts.type)) {
|
||||
// we find page in cache, use it
|
||||
*handle = PageHandle(std::move(cache_handle));
|
||||
opts.stats->cached_pages_num++;
|
||||
@ -189,9 +189,9 @@ Status PageIO::read_and_decompress_page(const PageReadOptions& opts, PageHandle*
|
||||
}
|
||||
|
||||
*body = Slice(page_slice.data, page_slice.size - 4 - footer_size);
|
||||
if (opts.use_page_cache) {
|
||||
if (opts.use_page_cache && cache->is_cache_available(opts.type)) {
|
||||
// insert this page into cache and return the cache handle
|
||||
cache->insert(cache_key, page_slice, &cache_handle, opts.kept_in_memory);
|
||||
cache->insert(cache_key, page_slice, &cache_handle, opts.type, opts.kept_in_memory);
|
||||
*handle = PageHandle(std::move(cache_handle));
|
||||
} else {
|
||||
*handle = PageHandle(page_slice);
|
||||
|
||||
@ -54,6 +54,10 @@ struct PageReadOptions {
|
||||
// if true, use DURABLE CachePriority in page cache
|
||||
// currently used for in memory olap table
|
||||
bool kept_in_memory = false;
|
||||
// for page cache allocation
|
||||
// page types are divided into DATA_PAGE & INDEX_PAGE
|
||||
// INDEX_PAGE including index_page, dict_page and short_key_page
|
||||
PageTypePB type;
|
||||
|
||||
void sanity_check() const {
|
||||
CHECK_NOTNULL(rblock);
|
||||
|
||||
@ -143,6 +143,7 @@ Status Segment::_load_index() {
|
||||
opts.codec = nullptr; // short key index page uses NO_COMPRESSION for now
|
||||
OlapReaderStatistics tmp_stats;
|
||||
opts.stats = &tmp_stats;
|
||||
opts.type = INDEX_PAGE;
|
||||
|
||||
Slice body;
|
||||
PageFooterPB footer;
|
||||
|
||||
@ -192,7 +192,8 @@ Status ExecEnv::_init_mem_tracker() {
|
||||
LOG(WARNING) << "Config storage_page_cache_limit is greater than memory size, config="
|
||||
<< config::storage_page_cache_limit << ", memory=" << MemInfo::physical_mem();
|
||||
}
|
||||
StoragePageCache::create_global_cache(storage_cache_limit);
|
||||
int32_t index_page_cache_percentage = config::index_page_cache_percentage;
|
||||
StoragePageCache::create_global_cache(storage_cache_limit, index_page_cache_percentage);
|
||||
|
||||
// TODO(zc): The current memory usage configuration is a bit confusing,
|
||||
// we need to sort out the use of memory
|
||||
|
||||
@ -27,22 +27,25 @@ public:
|
||||
virtual ~StoragePageCacheTest() {}
|
||||
};
|
||||
|
||||
TEST(StoragePageCacheTest, normal) {
|
||||
StoragePageCache cache(kNumShards * 2048);
|
||||
// All cache space is allocated to data pages
|
||||
TEST(StoragePageCacheTest, data_page_only) {
|
||||
StoragePageCache cache(kNumShards * 2048, 0);
|
||||
|
||||
StoragePageCache::CacheKey key("abc", 0);
|
||||
StoragePageCache::CacheKey memory_key("mem", 0);
|
||||
|
||||
segment_v2::PageTypePB page_type = segment_v2::DATA_PAGE;
|
||||
|
||||
{
|
||||
// insert normal page
|
||||
char* buf = new char[1024];
|
||||
PageCacheHandle handle;
|
||||
Slice data(buf, 1024);
|
||||
cache.insert(key, data, &handle, false);
|
||||
cache.insert(key, data, &handle, page_type, false);
|
||||
|
||||
ASSERT_EQ(handle.data().data, buf);
|
||||
|
||||
auto found = cache.lookup(key, &handle);
|
||||
auto found = cache.lookup(key, &handle, page_type);
|
||||
ASSERT_TRUE(found);
|
||||
ASSERT_EQ(buf, handle.data().data);
|
||||
}
|
||||
@ -52,11 +55,11 @@ TEST(StoragePageCacheTest, normal) {
|
||||
char* buf = new char[1024];
|
||||
PageCacheHandle handle;
|
||||
Slice data(buf, 1024);
|
||||
cache.insert(memory_key, data, &handle, true);
|
||||
cache.insert(memory_key, data, &handle, page_type, true);
|
||||
|
||||
ASSERT_EQ(handle.data().data, buf);
|
||||
|
||||
auto found = cache.lookup(memory_key, &handle);
|
||||
auto found = cache.lookup(memory_key, &handle, page_type);
|
||||
ASSERT_TRUE(found);
|
||||
}
|
||||
|
||||
@ -65,23 +68,182 @@ TEST(StoragePageCacheTest, normal) {
|
||||
StoragePageCache::CacheKey key("bcd", i);
|
||||
PageCacheHandle handle;
|
||||
Slice data(new char[1024], 1024);
|
||||
cache.insert(key, data, &handle, false);
|
||||
cache.insert(key, data, &handle, page_type, false);
|
||||
}
|
||||
|
||||
// cache miss
|
||||
{
|
||||
PageCacheHandle handle;
|
||||
StoragePageCache::CacheKey miss_key("abc", 1);
|
||||
auto found = cache.lookup(miss_key, &handle);
|
||||
auto found = cache.lookup(miss_key, &handle, page_type);
|
||||
ASSERT_FALSE(found);
|
||||
}
|
||||
|
||||
// cache miss for eliminated key
|
||||
{
|
||||
PageCacheHandle handle;
|
||||
auto found = cache.lookup(key, &handle);
|
||||
auto found = cache.lookup(key, &handle, page_type);
|
||||
ASSERT_FALSE(found);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// All cache space is allocated to index pages
|
||||
TEST(StoragePageCacheTest, index_page_only) {
|
||||
StoragePageCache cache(kNumShards * 2048, 100);
|
||||
|
||||
StoragePageCache::CacheKey key("abc", 0);
|
||||
StoragePageCache::CacheKey memory_key("mem", 0);
|
||||
|
||||
segment_v2::PageTypePB page_type = segment_v2::INDEX_PAGE;
|
||||
|
||||
{
|
||||
// insert normal page
|
||||
char* buf = new char[1024];
|
||||
PageCacheHandle handle;
|
||||
Slice data(buf, 1024);
|
||||
cache.insert(key, data, &handle, page_type, false);
|
||||
|
||||
ASSERT_EQ(handle.data().data, buf);
|
||||
|
||||
auto found = cache.lookup(key, &handle, page_type);
|
||||
ASSERT_TRUE(found);
|
||||
ASSERT_EQ(buf, handle.data().data);
|
||||
}
|
||||
|
||||
{
|
||||
// insert in_memory page
|
||||
char* buf = new char[1024];
|
||||
PageCacheHandle handle;
|
||||
Slice data(buf, 1024);
|
||||
cache.insert(memory_key, data, &handle, page_type, true);
|
||||
|
||||
ASSERT_EQ(handle.data().data, buf);
|
||||
|
||||
auto found = cache.lookup(memory_key, &handle, page_type);
|
||||
ASSERT_TRUE(found);
|
||||
}
|
||||
|
||||
// put too many page to eliminate first page
|
||||
for (int i = 0; i < 10 * kNumShards; ++i) {
|
||||
StoragePageCache::CacheKey key("bcd", i);
|
||||
PageCacheHandle handle;
|
||||
Slice data(new char[1024], 1024);
|
||||
cache.insert(key, data, &handle, page_type, false);
|
||||
}
|
||||
|
||||
// cache miss
|
||||
{
|
||||
PageCacheHandle handle;
|
||||
StoragePageCache::CacheKey miss_key("abc", 1);
|
||||
auto found = cache.lookup(miss_key, &handle, page_type);
|
||||
ASSERT_FALSE(found);
|
||||
}
|
||||
|
||||
// cache miss for eliminated key
|
||||
{
|
||||
PageCacheHandle handle;
|
||||
auto found = cache.lookup(key, &handle, page_type);
|
||||
ASSERT_FALSE(found);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cache space is allocated by index_page_cache_ratio
|
||||
TEST(StoragePageCacheTest, mixed_pages) {
|
||||
StoragePageCache cache(kNumShards * 2048, 10);
|
||||
|
||||
StoragePageCache::CacheKey data_key("data", 0);
|
||||
StoragePageCache::CacheKey index_key("index", 0);
|
||||
StoragePageCache::CacheKey data_key_mem("data_mem", 0);
|
||||
StoragePageCache::CacheKey index_key_mem("index_mem", 0);
|
||||
|
||||
segment_v2::PageTypePB page_type_data = segment_v2::DATA_PAGE;
|
||||
segment_v2::PageTypePB page_type_index = segment_v2::INDEX_PAGE;
|
||||
|
||||
{
|
||||
// insert both normal pages
|
||||
char* buf_data = new char[1024];
|
||||
char* buf_index = new char[1024];
|
||||
PageCacheHandle data_handle, index_handle;
|
||||
Slice data(buf_data, 1024), index(buf_index, 1024);
|
||||
cache.insert(data_key, data, &data_handle, page_type_data, false);
|
||||
cache.insert(index_key, index, &index_handle, page_type_index, false);
|
||||
|
||||
ASSERT_EQ(data_handle.data().data, buf_data);
|
||||
ASSERT_EQ(index_handle.data().data, buf_index);
|
||||
|
||||
auto found_data = cache.lookup(data_key, &data_handle, page_type_data);
|
||||
auto found_index = cache.lookup(index_key, &index_handle, page_type_index);
|
||||
ASSERT_TRUE(found_data);
|
||||
ASSERT_TRUE(found_index);
|
||||
ASSERT_EQ(buf_data, data_handle.data().data);
|
||||
ASSERT_EQ(buf_index, index_handle.data().data);
|
||||
}
|
||||
|
||||
{
|
||||
// insert both in_memory pages
|
||||
char* buf_data = new char[1024];
|
||||
char* buf_index = new char[1024];
|
||||
PageCacheHandle data_handle, index_handle;
|
||||
Slice data(buf_data, 1024), index(buf_index, 1024);
|
||||
cache.insert(data_key_mem, data, &data_handle, page_type_data, true);
|
||||
cache.insert(index_key_mem, index, &index_handle, page_type_index, true);
|
||||
|
||||
ASSERT_EQ(data_handle.data().data, buf_data);
|
||||
ASSERT_EQ(index_handle.data().data, buf_index);
|
||||
|
||||
auto found_data = cache.lookup(data_key_mem, &data_handle, page_type_data);
|
||||
auto found_index = cache.lookup(index_key_mem, &index_handle, page_type_index);
|
||||
ASSERT_TRUE(found_data);
|
||||
ASSERT_TRUE(found_index);
|
||||
}
|
||||
|
||||
// put too many page to eliminate first page of both cache
|
||||
for (int i = 0; i < 10 * kNumShards; ++i) {
|
||||
StoragePageCache::CacheKey key("bcd", i);
|
||||
PageCacheHandle handle;
|
||||
Slice data(new char[1024], 1024), index(new char[1024], 1024);
|
||||
cache.insert(key, data, &handle, page_type_data, false);
|
||||
cache.insert(key, index, &handle, page_type_index, false);
|
||||
}
|
||||
|
||||
// cache miss by key
|
||||
{
|
||||
PageCacheHandle data_handle, index_handle;
|
||||
StoragePageCache::CacheKey miss_key("abc", 1);
|
||||
auto found_data = cache.lookup(miss_key, &data_handle, page_type_data);
|
||||
auto found_index = cache.lookup(miss_key, &index_handle, page_type_index);
|
||||
ASSERT_FALSE(found_data);
|
||||
ASSERT_FALSE(found_index);
|
||||
}
|
||||
|
||||
// cache miss by page type
|
||||
{
|
||||
PageCacheHandle data_handle, index_handle;
|
||||
StoragePageCache::CacheKey miss_key_data("data_miss", 1);
|
||||
StoragePageCache::CacheKey miss_key_index("index_miss", 1);
|
||||
char* buf_data = new char[1024];
|
||||
char* buf_index = new char[1024];
|
||||
Slice data(buf_data, 1024), index(buf_index, 1024);
|
||||
cache.insert(miss_key_data, data, &data_handle, page_type_data, false);
|
||||
cache.insert(miss_key_index, index, &index_handle, page_type_index, false);
|
||||
|
||||
auto found_data = cache.lookup(miss_key_data, &data_handle, page_type_index);
|
||||
auto found_index = cache.lookup(miss_key_index, &index_handle, page_type_data);
|
||||
ASSERT_FALSE(found_data);
|
||||
ASSERT_FALSE(found_index);
|
||||
}
|
||||
|
||||
// cache miss for eliminated key
|
||||
{
|
||||
PageCacheHandle data_handle, index_handle;
|
||||
auto found_data = cache.lookup(data_key, &data_handle, page_type_data);
|
||||
auto found_index = cache.lookup(index_key, &index_handle, page_type_index);
|
||||
ASSERT_FALSE(found_data);
|
||||
ASSERT_FALSE(found_index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace doris
|
||||
|
||||
@ -353,7 +353,7 @@ TEST_F(BetaRowsetTest, BasicFunctionTest) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -298,7 +298,7 @@ TEST_F(RowsetConverterTest, TestConvertBetaRowsetToAlpha) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -238,7 +238,7 @@ TEST_F(BitmapIndexTest, test_null) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -291,7 +291,7 @@ TEST_F(BloomFilterIndexReaderWriterTest, test_decimal) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -673,7 +673,7 @@ TEST_F(ColumnReaderWriterTest, test_default_value) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ TEST_F(OrdinalPageIndexTest, one_data_page) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -1160,7 +1160,7 @@ TEST_F(SegmentReaderWriterTest, TestBloomFilterIndexUniqueModel) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ TEST_F(ColumnZoneMapTest, NormalTestCharPage) {
|
||||
} // namespace doris
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
doris::StoragePageCache::create_global_cache(1 << 30);
|
||||
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@ -720,6 +720,11 @@ Indicates how many tablets in this data directory failed to load. At the same ti
|
||||
|
||||
### `storage_page_cache_limit`
|
||||
|
||||
### `index_page_cache_percentage`
|
||||
* Type: int32
|
||||
* Description: Index page cache as a percentage of total storage page cache, value range is [0, 100]
|
||||
* Default value: 10
|
||||
|
||||
### `storage_root_path`
|
||||
|
||||
* Type: string
|
||||
|
||||
@ -720,6 +720,11 @@ load tablets from header failed, failed tablets size: xxx, path=xxx
|
||||
|
||||
### `storage_page_cache_limit`
|
||||
|
||||
### `index_page_cache_percentage`
|
||||
* 类型:int32
|
||||
* 描述:索引页缓存占总页面缓存的百分比,取值为[0, 100]。
|
||||
* 默认值:10
|
||||
|
||||
### `storage_root_path`
|
||||
|
||||
* 类型:string
|
||||
|
||||
Reference in New Issue
Block a user