/root/doris/be/src/olap/page_cache.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Licensed to the Apache Software Foundation (ASF) under one | 
| 2 |  | // or more contributor license agreements.  See the NOTICE file | 
| 3 |  | // distributed with this work for additional information | 
| 4 |  | // regarding copyright ownership.  The ASF licenses this file | 
| 5 |  | // to you under the Apache License, Version 2.0 (the | 
| 6 |  | // "License"); you may not use this file except in compliance | 
| 7 |  | // with the License.  You may obtain a copy of the License at | 
| 8 |  | // | 
| 9 |  | //   http://www.apache.org/licenses/LICENSE-2.0 | 
| 10 |  | // | 
| 11 |  | // Unless required by applicable law or agreed to in writing, | 
| 12 |  | // software distributed under the License is distributed on an | 
| 13 |  | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| 14 |  | // KIND, either express or implied.  See the License for the | 
| 15 |  | // specific language governing permissions and limitations | 
| 16 |  | // under the License. | 
| 17 |  |  | 
| 18 |  | #include "olap/page_cache.h" | 
| 19 |  |  | 
| 20 |  | #include <gen_cpp/segment_v2.pb.h> | 
| 21 |  | #include <glog/logging.h> | 
| 22 |  |  | 
| 23 |  | #include <ostream> | 
| 24 |  |  | 
| 25 |  | #include "runtime/exec_env.h" | 
| 26 |  |  | 
| 27 |  | namespace doris { | 
| 28 |  |  | 
| 29 |  | template <typename T> | 
| 30 |  | MemoryTrackedPageBase<T>::MemoryTrackedPageBase(size_t size, bool use_cache, | 
| 31 |  |                                                 segment_v2::PageTypePB page_type) | 
| 32 | 54.5k |         : _size(size) { | 
| 33 | 54.5k |     if (use_cache) {  Branch (33:9): [True: 6.09k, False: 43.5k]
  Branch (33:9): [True: 4.92k, False: 0]
 | 
| 34 | 11.0k |         _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type); | 
| 35 | 43.5k |     } else { | 
| 36 | 43.5k |         _mem_tracker_by_allocator = | 
| 37 | 43.5k |                 thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr(); | 
| 38 | 43.5k |     } | 
| 39 | 54.5k | } _ZN5doris21MemoryTrackedPageBaseIPcEC2EmbNS_10segment_v210PageTypePBE| Line | Count | Source |  | 32 | 49.5k |         : _size(size) { |  | 33 | 49.5k |     if (use_cache) {  Branch (33:9): [True: 6.09k, False: 43.5k]
 |  | 34 | 6.09k |         _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type); |  | 35 | 43.5k |     } else { |  | 36 | 43.5k |         _mem_tracker_by_allocator = |  | 37 | 43.5k |                 thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr(); |  | 38 | 43.5k |     } |  | 39 | 49.5k | } | 
_ZN5doris21MemoryTrackedPageBaseISt10shared_ptrINS_10segment_v215SegmentFooterPBEEEC2EmbNS2_10PageTypePBE| Line | Count | Source |  | 32 | 4.92k |         : _size(size) { |  | 33 | 4.92k |     if (use_cache) {  Branch (33:9): [True: 4.92k, False: 0]
 |  | 34 | 4.92k |         _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type); |  | 35 | 4.92k |     } else { |  | 36 | 0 |         _mem_tracker_by_allocator = |  | 37 | 0 |                 thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr(); |  | 38 | 0 |     } |  | 39 | 4.92k | } | 
 | 
| 40 |  |  | 
| 41 |  | MemoryTrackedPageWithPageEntity::MemoryTrackedPageWithPageEntity(size_t size, bool use_cache, | 
| 42 |  |                                                                  segment_v2::PageTypePB page_type) | 
| 43 | 49.5k |         : MemoryTrackedPageBase<char*>(size, use_cache, page_type), _capacity(size) { | 
| 44 | 49.5k |     { | 
| 45 | 49.5k |         SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(this->_mem_tracker_by_allocator); | Line | Count | Source |  | 76 | 49.5k |     auto VARNAME_LINENUM(scoped_tls_stmtl) = doris::ScopedInitThreadContext() | 
 | 
| 46 | 49.5k |         this->_data = reinterpret_cast<char*>( | 
| 47 | 49.5k |                 Allocator<false>::alloc(this->_capacity, ALLOCATOR_ALIGNMENT_16)); | 
| 48 | 49.5k |     } | 
| 49 | 49.5k | } | 
| 50 |  |  | 
| 51 | 44.7k | MemoryTrackedPageWithPageEntity::~MemoryTrackedPageWithPageEntity() { | 
| 52 | 44.7k |     if (this->_data != nullptr) {  Branch (52:9): [True: 44.7k, False: 0]
 | 
| 53 | 44.7k |         DCHECK(this->_capacity != 0 && this->_size != 0); | 
| 54 | 44.7k |         SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(this->_mem_tracker_by_allocator); | Line | Count | Source |  | 76 | 44.7k |     auto VARNAME_LINENUM(scoped_tls_stmtl) = doris::ScopedInitThreadContext() | 
 | 
| 55 | 44.7k |         Allocator<false>::free(this->_data, this->_capacity); | 
| 56 | 44.7k |     } | 
| 57 | 44.7k | } | 
| 58 |  |  | 
| 59 |  | template <typename T> | 
| 60 |  | MemoryTrackedPageWithPagePtr<T>::MemoryTrackedPageWithPagePtr(size_t size, | 
| 61 |  |                                                               segment_v2::PageTypePB page_type) | 
| 62 | 4.92k |         : MemoryTrackedPageBase<std::shared_ptr<T>>(size, true, page_type) { | 
| 63 | 4.92k |     DCHECK(this->_size > 0); | 
| 64 | 4.92k |     this->_size = size; | 
| 65 | 4.92k |     this->_mem_tracker_by_allocator->consume(this->_size); | 
| 66 | 4.92k | } | 
| 67 |  |  | 
| 68 |  | template <typename T> | 
| 69 | 2 | MemoryTrackedPageWithPagePtr<T>::~MemoryTrackedPageWithPagePtr() { | 
| 70 | 2 |     DCHECK(this->_size > 0); | 
| 71 | 2 |     this->_mem_tracker_by_allocator->release(this->_size); | 
| 72 | 2 | } | 
| 73 |  |  | 
| 74 |  | StoragePageCache* StoragePageCache::create_global_cache(size_t capacity, | 
| 75 |  |                                                         int32_t index_cache_percentage, | 
| 76 |  |                                                         int64_t pk_index_cache_capacity, | 
| 77 | 1 |                                                         uint32_t num_shards) { | 
| 78 | 1 |     return new StoragePageCache(capacity, index_cache_percentage, pk_index_cache_capacity, | 
| 79 | 1 |                                 num_shards); | 
| 80 | 1 | } | 
| 81 |  |  | 
| 82 |  | StoragePageCache::StoragePageCache(size_t capacity, int32_t index_cache_percentage, | 
| 83 |  |                                    int64_t pk_index_cache_capacity, uint32_t num_shards) | 
| 84 | 5 |         : _index_cache_percentage(index_cache_percentage) { | 
| 85 | 5 |     if (index_cache_percentage == 0) {  Branch (85:9): [True: 2, False: 3]
 | 
| 86 | 2 |         _data_page_cache = std::make_unique<DataPageCache>(capacity, num_shards); | 
| 87 | 3 |     } else if (index_cache_percentage == 100) {  Branch (87:16): [True: 1, False: 2]
 | 
| 88 | 1 |         _index_page_cache = std::make_unique<IndexPageCache>(capacity, num_shards); | 
| 89 | 2 |     } else if (index_cache_percentage > 0 && index_cache_percentage < 100) {  Branch (89:16): [True: 2, False: 0]
  Branch (89:46): [True: 2, False: 0]
 | 
| 90 | 2 |         _data_page_cache = std::make_unique<DataPageCache>( | 
| 91 | 2 |                 capacity * (100 - index_cache_percentage) / 100, num_shards); | 
| 92 | 2 |         _index_page_cache = std::make_unique<IndexPageCache>( | 
| 93 | 2 |                 capacity * index_cache_percentage / 100, num_shards); | 
| 94 | 2 |     } else { | 
| 95 | 0 |         CHECK(false) << "invalid index page cache percentage"; | 
| 96 | 0 |     } | 
| 97 |  |  | 
| 98 | 5 |     _pk_index_page_cache = std::make_unique<PKIndexPageCache>(pk_index_cache_capacity, num_shards); | 
| 99 | 5 | } | 
| 100 |  |  | 
| 101 |  | bool StoragePageCache::lookup(const CacheKey& key, PageCacheHandle* handle, | 
| 102 | 12.5k |                               segment_v2::PageTypePB page_type) { | 
| 103 | 12.5k |     auto* cache = _get_page_cache(page_type); | 
| 104 | 12.5k |     auto* lru_handle = cache->lookup(key.encode()); | 
| 105 | 12.5k |     if (lru_handle == nullptr) {  Branch (105:9): [True: 10.0k, False: 2.44k]
 | 
| 106 | 10.0k |         return false; | 
| 107 | 10.0k |     } | 
| 108 | 2.44k |     *handle = PageCacheHandle(cache, lru_handle); | 
| 109 | 2.44k |     return true; | 
| 110 | 12.5k | } | 
| 111 |  |  | 
| 112 |  | void StoragePageCache::insert(const CacheKey& key, DataPage* data, PageCacheHandle* handle, | 
| 113 | 5.97k |                               segment_v2::PageTypePB page_type, bool in_memory) { | 
| 114 | 5.97k |     CachePriority priority = CachePriority::NORMAL; | 
| 115 | 5.97k |     if (in_memory) {  Branch (115:9): [True: 8, False: 5.96k]
 | 
| 116 | 8 |         priority = CachePriority::DURABLE; | 
| 117 | 8 |     } | 
| 118 |  |  | 
| 119 | 5.97k |     auto* cache = _get_page_cache(page_type); | 
| 120 | 5.97k |     auto* lru_handle = cache->insert(key.encode(), data, data->capacity(), 0, priority); | 
| 121 | 5.97k |     DCHECK(lru_handle != nullptr); | 
| 122 | 5.97k |     *handle = PageCacheHandle(cache, lru_handle); | 
| 123 | 5.97k | } | 
| 124 |  |  | 
| 125 |  | template <typename T> | 
| 126 |  | void StoragePageCache::insert(const CacheKey& key, T data, size_t size, PageCacheHandle* handle, | 
| 127 | 4.92k |                               segment_v2::PageTypePB page_type, bool in_memory) { | 
| 128 | 4.92k |     static_assert(std::is_same<typename std::remove_cv<T>::type, | 
| 129 | 4.92k |                                std::shared_ptr<typename T::element_type>>::value, | 
| 130 | 4.92k |                   "Second argument must be a std::shared_ptr"); | 
| 131 | 4.92k |     using ValueType = typename T::element_type; // Type that shared_ptr points to | 
| 132 |  |  | 
| 133 | 4.92k |     CachePriority priority = CachePriority::NORMAL; | 
| 134 | 4.92k |     if (in_memory) {  Branch (134:9): [True: 0, False: 4.92k]
 | 
| 135 | 0 |         priority = CachePriority::DURABLE; | 
| 136 | 0 |     } | 
| 137 |  |  | 
| 138 | 4.92k |     auto* cache = _get_page_cache(page_type); | 
| 139 |  |     // Lify cycle of page will be managed by StoragePageCache | 
| 140 | 4.92k |     auto page = std::make_unique<MemoryTrackedPageWithPagePtr<ValueType>>(size, page_type); | 
| 141 |  |     // Lify cycle of data will be managed by StoragePageCache and user at the same time. | 
| 142 | 4.92k |     page->set_data(data); | 
| 143 |  |  | 
| 144 | 4.92k |     auto* lru_handle = cache->insert(key.encode(), page.get(), size, 0, priority); | 
| 145 | 4.92k |     DCHECK(lru_handle != nullptr); | 
| 146 | 4.92k |     *handle = PageCacheHandle(cache, lru_handle); | 
| 147 |  |     // Now page is managed by StoragePageCache. | 
| 148 | 4.92k |     page.release(); | 
| 149 | 4.92k | } | 
| 150 |  |  | 
| 151 | 983 | Slice PageCacheHandle::data() const { | 
| 152 | 983 |     auto* cache_value = (DataPage*)_cache->value(_handle); | 
| 153 | 983 |     return {cache_value->data(), cache_value->size()}; | 
| 154 | 983 | } | 
| 155 |  |  | 
| 156 |  | template void StoragePageCache::insert(const CacheKey& key, | 
| 157 |  |                                        std::shared_ptr<segment_v2::SegmentFooterPB> data, | 
| 158 |  |                                        size_t size, PageCacheHandle* handle, | 
| 159 |  |                                        segment_v2::PageTypePB page_type, bool in_memory); | 
| 160 |  |  | 
| 161 |  | template class MemoryTrackedPageWithPagePtr<segment_v2::SegmentFooterPB>; | 
| 162 |  |  | 
| 163 |  | } // namespace doris |