From d9ca8b6093427d102845ab938ff4dd667539a502 Mon Sep 17 00:00:00 2001 From: bobhan1 Date: Wed, 2 Jul 2025 14:59:37 +0800 Subject: [PATCH 1/4] move --- be/src/olap/tablet_meta.cpp | 50 ++++++++++++++++++------------- be/src/olap/tablet_meta.h | 51 +++++++++----------------------- be/src/runtime/exec_env.h | 4 +++ be/src/runtime/exec_env_init.cpp | 3 ++ 4 files changed, 50 insertions(+), 58 deletions(-) diff --git a/be/src/olap/tablet_meta.cpp b/be/src/olap/tablet_meta.cpp index 83c1d84547e54d..e301db08ffe75c 100644 --- a/be/src/olap/tablet_meta.cpp +++ b/be/src/olap/tablet_meta.cpp @@ -1086,7 +1086,16 @@ bool operator!=(const TabletMeta& a, const TabletMeta& b) { return !(a == b); } -DeleteBitmap::DeleteBitmap(int64_t tablet_id) : _tablet_id(tablet_id) { +DeleteBitmapAggCache::DeleteBitmapAggCache(size_t capacity) + : LRUCachePolicy(CachePolicy::CacheType::DELETE_BITMAP_AGG_CACHE, capacity, + LRUCacheType::SIZE, config::delete_bitmap_agg_cache_stale_sweep_time_sec, + 256) {} + +DeleteBitmapAggCache* DeleteBitmapAggCache::instance() { + return ExecEnv::GetInstance()->delete_bitmap_agg_cache(); +} + +DeleteBitmapAggCache* DeleteBitmapAggCache::create_instance() { // The default delete bitmap cache is set to 100MB, // which can be insufficient and cause performance issues when the amount of user data is large. // To mitigate the problem of an inadequate cache, @@ -1095,12 +1104,12 @@ DeleteBitmap::DeleteBitmap(int64_t tablet_id) : _tablet_id(tablet_id) { int64_t delete_bitmap_agg_cache_cache_limit = ParseUtil::parse_mem_spec(config::delete_bitmap_dynamic_agg_cache_limit, MemInfo::mem_limit(), MemInfo::physical_mem(), &is_percent); - _agg_cache.reset(new AggCache(delete_bitmap_agg_cache_cache_limit > - config::delete_bitmap_agg_cache_capacity - ? delete_bitmap_agg_cache_cache_limit - : config::delete_bitmap_agg_cache_capacity)); + return new DeleteBitmapAggCache(std::max(delete_bitmap_agg_cache_cache_limit, + config::delete_bitmap_agg_cache_capacity)); } +DeleteBitmap::DeleteBitmap(int64_t tablet_id) : _tablet_id(tablet_id) {} + DeleteBitmap::DeleteBitmap(const DeleteBitmap& o) { delete_bitmap = o.delete_bitmap; // just copy data _tablet_id = o._tablet_id; @@ -1398,20 +1407,20 @@ static std::string agg_cache_key(int64_t tablet_id, const DeleteBitmap::BitmapKe std::shared_ptr DeleteBitmap::get_agg(const BitmapKey& bmk) const { std::string key_str = agg_cache_key(_tablet_id, bmk); // Cache key container CacheKey key(key_str); - Cache::Handle* handle = _agg_cache->repr()->lookup(key); + Cache::Handle* handle = DeleteBitmapAggCache::instance()->lookup(key); - AggCache::Value* val = - handle == nullptr - ? nullptr - : reinterpret_cast(_agg_cache->repr()->value(handle)); + DeleteBitmapAggCache::Value* val = + handle == nullptr ? nullptr + : reinterpret_cast( + DeleteBitmapAggCache::instance()->value(handle)); // FIXME: do we need a mutex here to get rid of duplicated initializations // of cache entries in some cases? if (val == nullptr) { // Renew if needed, put a new Value to cache - val = new AggCache::Value(); + val = new DeleteBitmapAggCache::Value(); Version start_version = config::enable_mow_get_agg_by_cache ? _get_rowset_cache_version(bmk) : 0; if (start_version > 0) { - Cache::Handle* handle2 = _agg_cache->repr()->lookup( + Cache::Handle* handle2 = DeleteBitmapAggCache::instance()->lookup( agg_cache_key(_tablet_id, {std::get<0>(bmk), std::get<1>(bmk), start_version})); DBUG_EXECUTE_IF("DeleteBitmap::get_agg.cache_miss", { @@ -1429,10 +1438,10 @@ std::shared_ptr DeleteBitmap::get_agg(const BitmapKey& bmk) co if (handle2 == nullptr || start_version > std::get<2>(bmk)) { start_version = 0; } else { - val->bitmap |= - reinterpret_cast(_agg_cache->repr()->value(handle2)) - ->bitmap; - _agg_cache->repr()->release(handle2); + val->bitmap |= reinterpret_cast( + DeleteBitmapAggCache::instance()->value(handle2)) + ->bitmap; + DeleteBitmapAggCache::instance()->release(handle2); VLOG_DEBUG << "get agg cache version=" << start_version << " for tablet=" << _tablet_id << ", rowset=" << std::get<0>(bmk).to_string() @@ -1452,8 +1461,9 @@ std::shared_ptr DeleteBitmap::get_agg(const BitmapKey& bmk) co val->bitmap |= bm; } } - size_t charge = val->bitmap.getSizeInBytes() + sizeof(AggCache::Value); - handle = _agg_cache->repr()->insert(key, val, charge, charge, CachePriority::NORMAL); + size_t charge = val->bitmap.getSizeInBytes() + sizeof(DeleteBitmapAggCache::Value); + handle = DeleteBitmapAggCache::instance()->insert(key, val, charge, charge, + CachePriority::NORMAL); if (config::enable_mow_get_agg_by_cache && !val->bitmap.isEmpty()) { std::lock_guard l(_rowset_cache_version_lock); // this version is already agg @@ -1480,7 +1490,7 @@ std::shared_ptr DeleteBitmap::get_agg(const BitmapKey& bmk) co // It is natural for the cache to reclaim the underlying memory return std::shared_ptr( - &val->bitmap, [this, handle](...) { _agg_cache->repr()->release(handle); }); + &val->bitmap, [handle](...) { DeleteBitmapAggCache::instance()->release(handle); }); } std::shared_ptr DeleteBitmap::get_agg_without_cache( @@ -1499,8 +1509,6 @@ std::shared_ptr DeleteBitmap::get_agg_without_cache( return bitmap; } -std::atomic DeleteBitmap::AggCache::s_repr {nullptr}; - std::string tablet_state_name(TabletState state) { switch (state) { case TABLET_NOTREADY: diff --git a/be/src/olap/tablet_meta.h b/be/src/olap/tablet_meta.h index 88df0e9feace8d..60a61e687bde6b 100644 --- a/be/src/olap/tablet_meta.h +++ b/be/src/olap/tablet_meta.h @@ -364,6 +364,20 @@ class TabletMeta : public MetadataAdder { mutable std::shared_mutex _meta_lock; }; +class DeleteBitmapAggCache : public LRUCachePolicy { +public: + DeleteBitmapAggCache(size_t capacity); + + static DeleteBitmapAggCache* instance(); + + static DeleteBitmapAggCache* create_instance(); + + class Value : public LRUCacheValueBase { + public: + roaring::Roaring bitmap; + }; +}; + /** * Wraps multiple bitmaps for recording rows (row id) that are deleted or * overwritten. For now, it's only used when unique key merge-on-write property @@ -565,46 +579,9 @@ class DeleteBitmap { std::set get_rowset_cache_version(); - class AggCachePolicy : public LRUCachePolicy { - public: - AggCachePolicy(size_t capacity) - : LRUCachePolicy(CachePolicy::CacheType::DELETE_BITMAP_AGG_CACHE, capacity, - LRUCacheType::SIZE, - config::delete_bitmap_agg_cache_stale_sweep_time_sec, 256) {} - }; - - class AggCache { - public: - class Value : public LRUCacheValueBase { - public: - roaring::Roaring bitmap; - }; - - AggCache(size_t size_in_bytes) { - static std::once_flag once; - std::call_once(once, [size_in_bytes] { - auto* tmp = new AggCachePolicy(size_in_bytes); - AggCache::s_repr.store(tmp, std::memory_order_release); - - // release the sigleton instance at program exit - std::atexit([] { - auto* ptr = AggCache::s_repr.exchange(nullptr, std::memory_order_acquire); - delete ptr; - }); - }); - - while (!s_repr.load(std::memory_order_acquire)) { - } - } - - static LRUCachePolicy* repr() { return s_repr.load(std::memory_order_acquire); } - static std::atomic s_repr; - }; - private: DeleteBitmap::Version _get_rowset_cache_version(const BitmapKey& bmk) const; - mutable std::shared_ptr _agg_cache; int64_t _tablet_id; mutable std::shared_mutex _rowset_cache_version_lock; mutable std::map> _rowset_cache_version; diff --git a/be/src/runtime/exec_env.h b/be/src/runtime/exec_env.h index 1a7d6df0961410..a261b88b6b7923 100644 --- a/be/src/runtime/exec_env.h +++ b/be/src/runtime/exec_env.h @@ -128,6 +128,7 @@ class WalManager; class DNSCache; class IndexPolicyMgr; struct SyncRowsetStats; +class DeleteBitmapAggCache; inline bool k_doris_exit = false; @@ -372,6 +373,8 @@ class ExecEnv { void set_stream_mgr(vectorized::VDataStreamMgr* vstream_mgr) { _vstream_mgr = vstream_mgr; } void clear_stream_mgr(); + DeleteBitmapAggCache* delete_bitmap_agg_cache() { return _delete_bitmap_agg_cache; } + private: ExecEnv(); @@ -499,6 +502,7 @@ class ExecEnv { segment_v2::InvertedIndexQueryCache* _inverted_index_query_cache = nullptr; QueryCache* _query_cache = nullptr; std::unique_ptr _file_cache_open_fd_cache; + DeleteBitmapAggCache* _delete_bitmap_agg_cache {nullptr}; pipeline::RuntimeFilterTimerQueue* _runtime_filter_timer_queue = nullptr; vectorized::DictionaryFactory* _dict_factory = nullptr; diff --git a/be/src/runtime/exec_env_init.cpp b/be/src/runtime/exec_env_init.cpp index bbc333ca356741..7e3dc22e77ef55 100644 --- a/be/src/runtime/exec_env_init.cpp +++ b/be/src/runtime/exec_env_init.cpp @@ -57,6 +57,7 @@ #include "olap/segment_loader.h" #include "olap/storage_engine.h" #include "olap/tablet_column_object_pool.h" +#include "olap/tablet_meta.h" #include "olap/tablet_schema_cache.h" #include "olap/wal/wal_manager.h" #include "pipeline/pipeline_tracing.h" @@ -334,6 +335,7 @@ Status ExecEnv::_init(const std::vector& store_paths, _tablet_schema_cache = TabletSchemaCache::create_global_schema_cache(config::tablet_schema_cache_capacity); + _delete_bitmap_agg_cache = DeleteBitmapAggCache::create_instance(); _tablet_column_object_pool = TabletColumnObjectPool::create_global_column_cache( config::tablet_schema_cache_capacity); @@ -753,6 +755,7 @@ void ExecEnv::destroy() { SAFE_DELETE(_segment_loader); SAFE_DELETE(_row_cache); SAFE_DELETE(_query_cache); + SAFE_DELETE(_delete_bitmap_agg_cache); // Free resource after threads are stopped. // Some threads are still running, like threads created by _new_load_stream_mgr ... From d2d27044e0a275233ddf0a255fa61d8f6e123a14 Mon Sep 17 00:00:00 2001 From: bobhan1 Date: Wed, 2 Jul 2025 18:41:28 +0800 Subject: [PATCH 2/4] fix beut --- be/src/runtime/exec_env.h | 1 + be/test/testutil/run_all_tests.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/be/src/runtime/exec_env.h b/be/src/runtime/exec_env.h index a261b88b6b7923..a01bff87bc9ec2 100644 --- a/be/src/runtime/exec_env.h +++ b/be/src/runtime/exec_env.h @@ -304,6 +304,7 @@ class ExecEnv { void set_cache_manager(CacheManager* cm) { this->_cache_manager = cm; } void set_process_profile(ProcessProfile* pp) { this->_process_profile = pp; } void set_tablet_schema_cache(TabletSchemaCache* c) { this->_tablet_schema_cache = c; } + void set_delete_bitmap_agg_cache(DeleteBitmapAggCache* c) { _delete_bitmap_agg_cache = c; } void set_tablet_column_object_pool(TabletColumnObjectPool* c) { this->_tablet_column_object_pool = c; } diff --git a/be/test/testutil/run_all_tests.cpp b/be/test/testutil/run_all_tests.cpp index 241a4c44d37bd1..222c288e7dac58 100644 --- a/be/test/testutil/run_all_tests.cpp +++ b/be/test/testutil/run_all_tests.cpp @@ -69,6 +69,8 @@ int main(int argc, char** argv) { doris::ExecEnv::GetInstance()->set_tablet_schema_cache( doris::TabletSchemaCache::create_global_schema_cache( doris::config::tablet_schema_cache_capacity)); + doris::ExecEnv::GetInstance()->set_delete_bitmap_agg_cache( + doris::DeleteBitmapAggCache::create_instance()); doris::ExecEnv::GetInstance()->set_tablet_column_object_pool( doris::TabletColumnObjectPool::create_global_column_cache( doris::config::tablet_schema_cache_capacity)); From e8e6bc8ed428eebf43f7646393ec17dc9f341726 Mon Sep 17 00:00:00 2001 From: bobhan1 Date: Wed, 2 Jul 2025 19:45:19 +0800 Subject: [PATCH 3/4] fix beut --- be/test/testutil/run_all_tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/be/test/testutil/run_all_tests.cpp b/be/test/testutil/run_all_tests.cpp index 222c288e7dac58..d55446147cfac6 100644 --- a/be/test/testutil/run_all_tests.cpp +++ b/be/test/testutil/run_all_tests.cpp @@ -26,6 +26,7 @@ #include "olap/page_cache.h" #include "olap/segment_loader.h" #include "olap/tablet_column_object_pool.h" +#include "olap/tablet_meta.h" #include "olap/tablet_schema_cache.h" #include "runtime/exec_env.h" #include "runtime/memory/cache_manager.h" From 4c517572876acc9b27fcc5827723d5beeaf25f06 Mon Sep 17 00:00:00 2001 From: bobhan1 Date: Wed, 2 Jul 2025 21:11:13 +0800 Subject: [PATCH 4/4] fix beut --- be/src/olap/tablet_meta.cpp | 13 ++----------- be/src/olap/tablet_meta.h | 2 +- be/src/runtime/exec_env_init.cpp | 11 ++++++++++- be/test/testutil/run_all_tests.cpp | 3 ++- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/be/src/olap/tablet_meta.cpp b/be/src/olap/tablet_meta.cpp index e301db08ffe75c..6d9736dcc5b4b2 100644 --- a/be/src/olap/tablet_meta.cpp +++ b/be/src/olap/tablet_meta.cpp @@ -1095,17 +1095,8 @@ DeleteBitmapAggCache* DeleteBitmapAggCache::instance() { return ExecEnv::GetInstance()->delete_bitmap_agg_cache(); } -DeleteBitmapAggCache* DeleteBitmapAggCache::create_instance() { - // The default delete bitmap cache is set to 100MB, - // which can be insufficient and cause performance issues when the amount of user data is large. - // To mitigate the problem of an inadequate cache, - // we will take the larger of 0.5% of the total memory and 100MB as the delete bitmap cache size. - bool is_percent = false; - int64_t delete_bitmap_agg_cache_cache_limit = - ParseUtil::parse_mem_spec(config::delete_bitmap_dynamic_agg_cache_limit, - MemInfo::mem_limit(), MemInfo::physical_mem(), &is_percent); - return new DeleteBitmapAggCache(std::max(delete_bitmap_agg_cache_cache_limit, - config::delete_bitmap_agg_cache_capacity)); +DeleteBitmapAggCache* DeleteBitmapAggCache::create_instance(size_t capacity) { + return new DeleteBitmapAggCache(capacity); } DeleteBitmap::DeleteBitmap(int64_t tablet_id) : _tablet_id(tablet_id) {} diff --git a/be/src/olap/tablet_meta.h b/be/src/olap/tablet_meta.h index 60a61e687bde6b..08b06aaec433c9 100644 --- a/be/src/olap/tablet_meta.h +++ b/be/src/olap/tablet_meta.h @@ -370,7 +370,7 @@ class DeleteBitmapAggCache : public LRUCachePolicy { static DeleteBitmapAggCache* instance(); - static DeleteBitmapAggCache* create_instance(); + static DeleteBitmapAggCache* create_instance(size_t capacity); class Value : public LRUCacheValueBase { public: diff --git a/be/src/runtime/exec_env_init.cpp b/be/src/runtime/exec_env_init.cpp index 7e3dc22e77ef55..56fb5b182c9c46 100644 --- a/be/src/runtime/exec_env_init.cpp +++ b/be/src/runtime/exec_env_init.cpp @@ -335,7 +335,6 @@ Status ExecEnv::_init(const std::vector& store_paths, _tablet_schema_cache = TabletSchemaCache::create_global_schema_cache(config::tablet_schema_cache_capacity); - _delete_bitmap_agg_cache = DeleteBitmapAggCache::create_instance(); _tablet_column_object_pool = TabletColumnObjectPool::create_global_column_cache( config::tablet_schema_cache_capacity); @@ -586,6 +585,16 @@ Status ExecEnv::_init_mem_env() { _query_cache = QueryCache::create_global_cache(config::query_cache_size * 1024L * 1024L); LOG(INFO) << "query cache memory limit: " << config::query_cache_size << "MB"; + // The default delete bitmap cache is set to 100MB, + // which can be insufficient and cause performance issues when the amount of user data is large. + // To mitigate the problem of an inadequate cache, + // we will take the larger of 0.5% of the total memory and 100MB as the delete bitmap cache size. + int64_t delete_bitmap_agg_cache_cache_limit = + ParseUtil::parse_mem_spec(config::delete_bitmap_dynamic_agg_cache_limit, + MemInfo::mem_limit(), MemInfo::physical_mem(), &is_percent); + _delete_bitmap_agg_cache = DeleteBitmapAggCache::create_instance(std::max( + delete_bitmap_agg_cache_cache_limit, config::delete_bitmap_agg_cache_capacity)); + return Status::OK(); } diff --git a/be/test/testutil/run_all_tests.cpp b/be/test/testutil/run_all_tests.cpp index d55446147cfac6..6f906ae0c28dd2 100644 --- a/be/test/testutil/run_all_tests.cpp +++ b/be/test/testutil/run_all_tests.cpp @@ -71,7 +71,8 @@ int main(int argc, char** argv) { doris::TabletSchemaCache::create_global_schema_cache( doris::config::tablet_schema_cache_capacity)); doris::ExecEnv::GetInstance()->set_delete_bitmap_agg_cache( - doris::DeleteBitmapAggCache::create_instance()); + doris::DeleteBitmapAggCache::create_instance( + doris::config::delete_bitmap_agg_cache_capacity)); doris::ExecEnv::GetInstance()->set_tablet_column_object_pool( doris::TabletColumnObjectPool::create_global_column_cache( doris::config::tablet_schema_cache_capacity));