This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 8a244d2bd2c branch-3.1: [Opt](mow) Move `DeleteBitmapAggCache` to 
`ExecEnv` #52649 (#52705)
8a244d2bd2c is described below

commit 8a244d2bd2cab2e89c6970b756694cdc388286fd
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jul 4 11:28:11 2025 +0800

    branch-3.1: [Opt](mow) Move `DeleteBitmapAggCache` to `ExecEnv` #52649 
(#52705)
    
    Cherry-picked from #52649
    
    Co-authored-by: bobhan1 <[email protected]>
---
 be/src/olap/tablet_meta.cpp        | 57 +++++++++++++++++++-------------------
 be/src/olap/tablet_meta.h          | 51 ++++++++++------------------------
 be/src/runtime/exec_env.h          |  5 ++++
 be/src/runtime/exec_env_init.cpp   | 12 ++++++++
 be/test/testutil/run_all_tests.cpp |  4 +++
 5 files changed, 63 insertions(+), 66 deletions(-)

diff --git a/be/src/olap/tablet_meta.cpp b/be/src/olap/tablet_meta.cpp
index f1c1213c0c4..ab225d1fcdb 100644
--- a/be/src/olap/tablet_meta.cpp
+++ b/be/src/olap/tablet_meta.cpp
@@ -1099,21 +1099,21 @@ bool operator!=(const TabletMeta& a, const TabletMeta& 
b) {
     return !(a == b);
 }
 
-DeleteBitmap::DeleteBitmap(int64_t tablet_id) : _tablet_id(tablet_id) {
-    // 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);
-    _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));
+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(size_t capacity) {
+    return new DeleteBitmapAggCache(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;
@@ -1407,20 +1407,20 @@ static std::string agg_cache_key(int64_t tablet_id, 
const DeleteBitmap::BitmapKe
 std::shared_ptr<roaring::Roaring> 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<AggCache::Value*>(_agg_cache->repr()->value(handle));
+    DeleteBitmapAggCache::Value* val =
+            handle == nullptr ? nullptr
+                              : reinterpret_cast<DeleteBitmapAggCache::Value*>(
+                                        
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", {
@@ -1438,10 +1438,10 @@ std::shared_ptr<roaring::Roaring> 
DeleteBitmap::get_agg(const BitmapKey& bmk) co
             if (handle2 == nullptr || start_version > std::get<2>(bmk)) {
                 start_version = 0;
             } else {
-                val->bitmap |=
-                        
reinterpret_cast<AggCache::Value*>(_agg_cache->repr()->value(handle2))
-                                ->bitmap;
-                _agg_cache->repr()->release(handle2);
+                val->bitmap |= reinterpret_cast<DeleteBitmapAggCache::Value*>(
+                                       
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()
@@ -1461,8 +1461,9 @@ std::shared_ptr<roaring::Roaring> 
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
@@ -1489,7 +1490,7 @@ std::shared_ptr<roaring::Roaring> 
DeleteBitmap::get_agg(const BitmapKey& bmk) co
 
     // It is natural for the cache to reclaim the underlying memory
     return std::shared_ptr<roaring::Roaring>(
-            &val->bitmap, [this, handle](...) { 
_agg_cache->repr()->release(handle); });
+            &val->bitmap, [handle](...) { 
DeleteBitmapAggCache::instance()->release(handle); });
 }
 
 std::shared_ptr<roaring::Roaring> DeleteBitmap::get_agg_without_cache(
@@ -1508,8 +1509,6 @@ std::shared_ptr<roaring::Roaring> 
DeleteBitmap::get_agg_without_cache(
     return bitmap;
 }
 
-std::atomic<DeleteBitmap::AggCachePolicy*> 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 a086e82e4a3..6e4b6719a20 100644
--- a/be/src/olap/tablet_meta.h
+++ b/be/src/olap/tablet_meta.h
@@ -364,6 +364,20 @@ private:
     mutable std::shared_mutex _meta_lock;
 };
 
+class DeleteBitmapAggCache : public LRUCachePolicy {
+public:
+    DeleteBitmapAggCache(size_t capacity);
+
+    static DeleteBitmapAggCache* instance();
+
+    static DeleteBitmapAggCache* create_instance(size_t capacity);
+
+    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 @@ public:
 
     std::set<RowsetId> 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<AggCachePolicy*> s_repr;
-    };
-
 private:
     DeleteBitmap::Version _get_rowset_cache_version(const BitmapKey& bmk) 
const;
 
-    mutable std::shared_ptr<AggCache> _agg_cache;
     int64_t _tablet_id;
     mutable std::shared_mutex _rowset_cache_version_lock;
     mutable std::map<RowsetId, std::map<SegmentId, Version>> 
_rowset_cache_version;
diff --git a/be/src/runtime/exec_env.h b/be/src/runtime/exec_env.h
index f3255be9291..4dae6f66122 100644
--- a/be/src/runtime/exec_env.h
+++ b/be/src/runtime/exec_env.h
@@ -126,6 +126,7 @@ class WalManager;
 class DNSCache;
 class IndexPolicyMgr;
 struct SyncRowsetStats;
+class DeleteBitmapAggCache;
 
 inline bool k_doris_exit = false;
 
@@ -305,6 +306,7 @@ public:
     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;
     }
@@ -372,6 +374,8 @@ public:
 
     bool check_auth_token(const std::string& auth_token);
 
+    DeleteBitmapAggCache* delete_bitmap_agg_cache() { return 
_delete_bitmap_agg_cache; }
+
 private:
     ExecEnv();
 
@@ -501,6 +505,7 @@ private:
     QueryCache* _query_cache = nullptr;
     std::shared_ptr<DummyLRUCache> _dummy_lru_cache = nullptr;
     std::unique_ptr<io::FDCache> _file_cache_open_fd_cache;
+    DeleteBitmapAggCache* _delete_bitmap_agg_cache {nullptr};
 
     pipeline::RuntimeFilterTimerQueue* _runtime_filter_timer_queue = nullptr;
 
diff --git a/be/src/runtime/exec_env_init.cpp b/be/src/runtime/exec_env_init.cpp
index ce841afc1d3..0fbc1e7af8a 100644
--- a/be/src/runtime/exec_env_init.cpp
+++ b/be/src/runtime/exec_env_init.cpp
@@ -55,6 +55,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"
@@ -581,6 +582,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();
 }
 
@@ -735,6 +746,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 ...
diff --git a/be/test/testutil/run_all_tests.cpp 
b/be/test/testutil/run_all_tests.cpp
index 810f3e0c28f..253d1729780 100644
--- a/be/test/testutil/run_all_tests.cpp
+++ b/be/test/testutil/run_all_tests.cpp
@@ -32,6 +32,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 "runtime/exec_env.h"
 #include "runtime/memory/cache_manager.h"
@@ -77,6 +78,9 @@ 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::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));


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to