Coverage Report

Created: 2025-04-28 18:47

/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
45.5k
        : _size(size) {
33
45.5k
    if (use_cache) {
34
10.7k
        _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type);
35
34.7k
    } else {
36
34.7k
        _mem_tracker_by_allocator =
37
34.7k
                thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr();
38
34.7k
    }
39
45.5k
}
_ZN5doris21MemoryTrackedPageBaseIPcEC2EmbNS_10segment_v210PageTypePBE
Line
Count
Source
32
40.7k
        : _size(size) {
33
40.7k
    if (use_cache) {
34
6.01k
        _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type);
35
34.7k
    } else {
36
34.7k
        _mem_tracker_by_allocator =
37
34.7k
                thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr();
38
34.7k
    }
39
40.7k
}
_ZN5doris21MemoryTrackedPageBaseISt10shared_ptrINS_10segment_v215SegmentFooterPBEEEC2EmbNS2_10PageTypePBE
Line
Count
Source
32
4.78k
        : _size(size) {
33
4.78k
    if (use_cache) {
34
4.78k
        _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type);
35
4.78k
    } else {
36
0
        _mem_tracker_by_allocator =
37
0
                thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_sptr();
38
0
    }
39
4.78k
}
40
41
MemoryTrackedPageWithPageEntity::MemoryTrackedPageWithPageEntity(size_t size, bool use_cache,
42
                                                                 segment_v2::PageTypePB page_type)
43
40.7k
        : MemoryTrackedPageBase<char*>(size, use_cache, page_type), _capacity(size) {
44
40.7k
    {
45
40.7k
        SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(this->_mem_tracker_by_allocator);
46
40.7k
        this->_data = reinterpret_cast<char*>(
47
40.7k
                Allocator<false>::alloc(this->_capacity, ALLOCATOR_ALIGNMENT_16));
48
40.7k
    }
49
40.7k
}
50
51
36.0k
MemoryTrackedPageWithPageEntity::~MemoryTrackedPageWithPageEntity() {
52
36.0k
    if (this->_data != nullptr) {
53
36.0k
        DCHECK(this->_capacity != 0 && this->_size != 0);
54
36.0k
        SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(this->_mem_tracker_by_allocator);
55
36.0k
        Allocator<false>::free(this->_data, this->_capacity);
56
36.0k
    }
57
36.0k
}
58
59
template <typename T>
60
MemoryTrackedPageWithPagePtr<T>::MemoryTrackedPageWithPagePtr(size_t size,
61
                                                              segment_v2::PageTypePB page_type)
62
4.78k
        : MemoryTrackedPageBase<std::shared_ptr<T>>(size, true, page_type) {
63
4.78k
    DCHECK(this->_size > 0);
64
4.78k
    this->_size = size;
65
4.78k
    this->_mem_tracker_by_allocator->consume(this->_size);
66
4.78k
}
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) {
86
2
        _data_page_cache = std::make_unique<DataPageCache>(capacity, num_shards);
87
3
    } else if (index_cache_percentage == 100) {
88
1
        _index_page_cache = std::make_unique<IndexPageCache>(capacity, num_shards);
89
2
    } else if (index_cache_percentage > 0 && index_cache_percentage < 100) {
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) {
106
9.87k
        return false;
107
9.87k
    }
108
2.63k
    *handle = PageCacheHandle(cache, lru_handle);
109
2.63k
    return true;
110
12.5k
}
111
112
void StoragePageCache::insert(const CacheKey& key, DataPage* data, PageCacheHandle* handle,
113
5.88k
                              segment_v2::PageTypePB page_type, bool in_memory) {
114
5.88k
    CachePriority priority = CachePriority::NORMAL;
115
5.88k
    if (in_memory) {
116
8
        priority = CachePriority::DURABLE;
117
8
    }
118
119
5.88k
    auto* cache = _get_page_cache(page_type);
120
5.88k
    auto* lru_handle = cache->insert(key.encode(), data, data->capacity(), 0, priority);
121
5.88k
    DCHECK(lru_handle != nullptr);
122
5.88k
    *handle = PageCacheHandle(cache, lru_handle);
123
5.88k
}
124
125
template <typename T>
126
void StoragePageCache::insert(const CacheKey& key, T data, size_t size, PageCacheHandle* handle,
127
4.78k
                              segment_v2::PageTypePB page_type, bool in_memory) {
128
4.78k
    static_assert(std::is_same<typename std::remove_cv<T>::type,
129
4.78k
                               std::shared_ptr<typename T::element_type>>::value,
130
4.78k
                  "Second argument must be a std::shared_ptr");
131
4.78k
    using ValueType = typename T::element_type; // Type that shared_ptr points to
132
133
4.78k
    CachePriority priority = CachePriority::NORMAL;
134
4.78k
    if (in_memory) {
135
0
        priority = CachePriority::DURABLE;
136
0
    }
137
138
4.78k
    auto* cache = _get_page_cache(page_type);
139
    // Lify cycle of page will be managed by StoragePageCache
140
4.78k
    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.78k
    page->set_data(data);
143
144
4.78k
    auto* lru_handle = cache->insert(key.encode(), page.get(), size, 0, priority);
145
4.78k
    DCHECK(lru_handle != nullptr);
146
4.78k
    *handle = PageCacheHandle(cache, lru_handle);
147
    // Now page is managed by StoragePageCache.
148
4.78k
    page.release();
149
4.78k
}
150
151
753
Slice PageCacheHandle::data() const {
152
753
    auto* cache_value = (DataPage*)_cache->value(_handle);
153
753
    return {cache_value->data(), cache_value->size()};
154
753
}
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