Skip to content

Commit 1b60452

Browse files
authored
No tracing memory usage of shared column data in MPPTask's memory tracker (#8131) (#8136)
close #8128
1 parent d956122 commit 1b60452

File tree

8 files changed

+81
-9
lines changed

8 files changed

+81
-9
lines changed

dbms/src/Common/MemoryTracker.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ static Poco::Logger * getLogger()
6565
return logger;
6666
}
6767

68+
static String storageMemoryUsageDetail()
69+
{
70+
return fmt::format(
71+
"non-query: peak={}, amount={}; "
72+
"shared-column-data: peak={}, amount={}.",
73+
root_of_non_query_mem_trackers ? formatReadableSizeWithBinarySuffix(root_of_non_query_mem_trackers->getPeak())
74+
: "0",
75+
root_of_non_query_mem_trackers ? formatReadableSizeWithBinarySuffix(root_of_non_query_mem_trackers->get())
76+
: "0",
77+
shared_column_data_mem_tracker ? formatReadableSizeWithBinarySuffix(shared_column_data_mem_tracker->getPeak())
78+
: "0",
79+
shared_column_data_mem_tracker ? formatReadableSizeWithBinarySuffix(shared_column_data_mem_tracker->get())
80+
: "0");
81+
}
82+
6883
void MemoryTracker::logPeakMemoryUsage() const
6984
{
7085
LOG_DEBUG(getLogger(), "Peak memory usage{}: {}.", (description ? " " + std::string(description) : ""), formatReadableSizeWithBinarySuffix(peak));
@@ -79,7 +94,12 @@ void MemoryTracker::alloc(Int64 size, bool check_memory_limit)
7994
Int64 will_be = size + amount.fetch_add(size, std::memory_order_relaxed);
8095

8196
if (!next.load(std::memory_order_relaxed))
97+
{
8298
CurrentMetrics::add(metric, size);
99+
// Only add shared column data size to root_of_query_mem_trackers.
100+
if (shared_column_data_mem_tracker && root_of_query_mem_trackers.get() == this)
101+
will_be += shared_column_data_mem_tracker->get();
102+
}
83103

84104
if (check_memory_limit)
85105
{
@@ -101,6 +121,7 @@ void MemoryTracker::alloc(Int64 size, bool check_memory_limit)
101121
(root_of_non_query_mem_trackers ? formatReadableSizeWithBinarySuffix(root_of_non_query_mem_trackers->peak) : "0"),
102122
(root_of_non_query_mem_trackers ? formatReadableSizeWithBinarySuffix(root_of_non_query_mem_trackers->amount) : "0"),
103123
proc_virt_size.load());
124+
fmt_buf.fmtAppend(" Memory usage of storage: {}", storageMemoryUsageDetail());
104125
throw DB::TiFlashException(fmt_buf.toString(), DB::Errors::Coprocessor::MemoryLimitExceeded);
105126
}
106127

@@ -118,7 +139,7 @@ void MemoryTracker::alloc(Int64 size, bool check_memory_limit)
118139
formatReadableSizeWithBinarySuffix(will_be),
119140
size,
120141
formatReadableSizeWithBinarySuffix(current_limit));
121-
142+
fmt_buf.fmtAppend(" Memory usage of storage: {}", storageMemoryUsageDetail());
122143
throw DB::TiFlashException(fmt_buf.toString(), DB::Errors::Coprocessor::MemoryLimitExceeded);
123144
}
124145
Int64 current_bytes_rss_larger_than_limit = bytes_rss_larger_than_limit.load(std::memory_order_relaxed);
@@ -150,7 +171,7 @@ void MemoryTracker::alloc(Int64 size, bool check_memory_limit)
150171
size,
151172
formatReadableSizeWithBinarySuffix(current_limit));
152173
}
153-
174+
fmt_buf.fmtAppend(" Memory usage of storage: {}", storageMemoryUsageDetail());
154175
throw DB::TiFlashException(fmt_buf.toString(), DB::Errors::Coprocessor::MemoryLimitExceeded);
155176
}
156177
}
@@ -224,6 +245,20 @@ thread_local MemoryTracker * current_memory_tracker = nullptr;
224245
std::shared_ptr<MemoryTracker> root_of_non_query_mem_trackers = MemoryTracker::createGlobalRoot();
225246
std::shared_ptr<MemoryTracker> root_of_query_mem_trackers = MemoryTracker::createGlobalRoot();
226247

248+
std::shared_ptr<MemoryTracker> shared_column_data_mem_tracker;
249+
250+
void initStorageMemoryTracker(Int64 limit, Int64 larger_than_limit)
251+
{
252+
LOG_INFO(
253+
getLogger(),
254+
"Storage task memory limit={}, larger_than_limit={}",
255+
formatReadableSizeWithBinarySuffix(limit),
256+
formatReadableSizeWithBinarySuffix(larger_than_limit));
257+
RUNTIME_CHECK(shared_column_data_mem_tracker == nullptr);
258+
shared_column_data_mem_tracker = MemoryTracker::create(limit);
259+
shared_column_data_mem_tracker->setBytesThatRssLargerThanLimit(larger_than_limit);
260+
}
261+
227262
namespace CurrentMemoryTracker
228263
{
229264
static Int64 MEMORY_TRACER_SUBMIT_THRESHOLD = 1024 * 1024; // 1 MiB

dbms/src/Common/MemoryTracker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ extern thread_local MemoryTracker * current_memory_tracker;
157157
extern std::shared_ptr<MemoryTracker> root_of_non_query_mem_trackers;
158158
extern std::shared_ptr<MemoryTracker> root_of_query_mem_trackers;
159159

160+
extern std::shared_ptr<MemoryTracker> shared_column_data_mem_tracker;
161+
void initStorageMemoryTracker(Int64 limit, Int64 larger_than_limit);
162+
160163
/// Convenience methods, that use current_memory_tracker if it is available.
161164
namespace CurrentMemoryTracker
162165
{

dbms/src/Common/PODArray.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <Common/Allocator.h>
1818
#include <Common/BitHelpers.h>
1919
#include <Common/Exception.h>
20+
#include <Common/MemoryTrackerSetter.h>
2021
#include <Common/memcpySmall.h>
2122
#include <common/likely.h>
2223
#include <common/strong_typedef.h>
@@ -104,6 +105,14 @@ class PODArrayBase : private boost::noncopyable
104105
char * c_end = null;
105106
char * c_end_of_storage = null; /// Does not include pad_right.
106107

108+
bool is_shared_memory;
109+
110+
[[nodiscard]] __attribute__((always_inline)) std::optional<MemoryTrackerSetter> swicthMemoryTracker()
111+
{
112+
return is_shared_memory ? std::make_optional<MemoryTrackerSetter>(true, shared_column_data_mem_tracker.get())
113+
: std::nullopt;
114+
}
115+
107116
/// The amount of memory occupied by the num_elements of the elements.
108117
static size_t byte_size(size_t num_elements) { return num_elements * ELEMENT_SIZE; }
109118

@@ -129,7 +138,10 @@ class PODArrayBase : private boost::noncopyable
129138
template <typename... TAllocatorParams>
130139
void alloc(size_t bytes, TAllocatorParams &&... allocator_params)
131140
{
132-
c_start = c_end = reinterpret_cast<char *>(TAllocator::alloc(bytes, std::forward<TAllocatorParams>(allocator_params)...)) + pad_left;
141+
auto guard = swicthMemoryTracker();
142+
c_start = c_end
143+
= reinterpret_cast<char *>(TAllocator::alloc(bytes, std::forward<TAllocatorParams>(allocator_params)...))
144+
+ pad_left;
133145
c_end_of_storage = c_start + bytes - pad_right - pad_left;
134146

135147
if (pad_left)
@@ -143,6 +155,7 @@ class PODArrayBase : private boost::noncopyable
143155

144156
unprotect();
145157

158+
auto guard = swicthMemoryTracker();
146159
TAllocator::free(c_start - pad_left, allocated_bytes());
147160
}
148161

@@ -157,6 +170,7 @@ class PODArrayBase : private boost::noncopyable
157170

158171
unprotect();
159172

173+
auto guard = swicthMemoryTracker();
160174
ptrdiff_t end_diff = c_end - c_start;
161175

162176
c_start = reinterpret_cast<char *>(
@@ -281,10 +295,11 @@ class PODArrayBase : private boost::noncopyable
281295
#endif
282296
}
283297

284-
~PODArrayBase()
285-
{
286-
dealloc();
287-
}
298+
~PODArrayBase() { dealloc(); }
299+
300+
PODArrayBase()
301+
: is_shared_memory(current_memory_tracker == nullptr)
302+
{}
288303
};
289304

290305
template <typename T, size_t INITIAL_SIZE = 4096, typename TAllocator = Allocator<false>, size_t pad_right_ = 0, size_t pad_left_ = 0>

dbms/src/Server/Server.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,9 @@ int Server::main(const std::vector<std::string> & /*args*/)
12391239
auto & blockable_bg_pool = global_context->initializeBlockableBackgroundPool(settings.background_pool_size);
12401240
// adjust the thread pool size according to settings and logical cores num
12411241
adjustThreadPoolSize(settings, server_info.cpu_info.logical_cores);
1242+
initStorageMemoryTracker(
1243+
settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity),
1244+
settings.bytes_that_rss_larger_than_limit);
12421245

12431246
/// PageStorage run mode has been determined above
12441247
if (!global_context->getSharedContextDisagg()->isDisaggregatedComputeMode())

dbms/src/Storages/DeltaMerge/File/DMFileReader.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <Columns/ColumnsCommon.h>
1616
#include <Common/CurrentMetrics.h>
17+
#include <Common/MemoryTracker.h>
1718
#include <Common/Stopwatch.h>
1819
#include <Common/escapeForFileName.h>
1920
#include <DataTypes/IDataType.h>
@@ -698,8 +699,15 @@ void DMFileReader::readColumn(ColumnDefine & column_define,
698699
size_t read_rows,
699700
size_t skip_packs)
700701
{
702+
bool has_concurrent_reader = DMFileReaderPool::instance().hasConcurrentReader(*this);
701703
if (!getCachedPacks(column_define.id, start_pack_id, pack_count, read_rows, column))
702704
{
705+
// If there are concurrent read requests, this data is likely to be shared.
706+
// So the allocation and deallocation of this data may not be in the same MemoryTracker.
707+
// This can lead to inaccurate memory statistics of MemoryTracker.
708+
// To solve this problem, we use a independent global memory tracker to trace the shared column data in ColumnSharingCacheMap.
709+
auto mem_tracker_guard
710+
= has_concurrent_reader ? std::make_optional<MemoryTrackerSetter>(true, nullptr) : std::nullopt;
703711
auto data_type = dmfile->getColumnStat(column_define.id).type;
704712
auto col = data_type->createColumn();
705713
readFromDisk(column_define, col, start_pack_id, read_rows, skip_packs, last_read_from_cache[column_define.id]);
@@ -711,7 +719,7 @@ void DMFileReader::readColumn(ColumnDefine & column_define,
711719
last_read_from_cache[column_define.id] = true;
712720
}
713721

714-
if (col_data_cache != nullptr)
722+
if (has_concurrent_reader && col_data_cache != nullptr)
715723
{
716724
DMFileReaderPool::instance().set(*this, column_define.id, start_pack_id, pack_count, column);
717725
}

dbms/src/Storages/DeltaMerge/ReadThread/ColumnSharingCache.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ void DMFileReaderPool::set(DMFileReader & from_reader, int64_t col_id, size_t st
6161
}
6262
}
6363

64+
// Check is there any concurrent DMFileReader with `from_reader`.
65+
bool DMFileReaderPool::hasConcurrentReader(DMFileReader & from_reader)
66+
{
67+
std::lock_guard lock(mtx);
68+
auto itr = readers.find(from_reader.path());
69+
return itr != readers.end() && itr->second.size() >= 2;
70+
}
71+
6472
DMFileReader * DMFileReaderPool::get(const std::string & name)
6573
{
6674
std::lock_guard lock(mtx);

dbms/src/Storages/DeltaMerge/ReadThread/ColumnSharingCache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ class DMFileReaderPool
224224
void add(DMFileReader & reader);
225225
void del(DMFileReader & reader);
226226
void set(DMFileReader & from_reader, int64_t col_id, size_t start, size_t count, ColumnPtr & col);
227+
bool hasConcurrentReader(DMFileReader & from_reader);
227228
// `get` is just for test.
228229
DMFileReader * get(const std::string & name);
229230

dbms/src/TestUtils/gtests_dbms_main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ int main(int argc, char ** argv)
6969
DB::tests::TiFlashTestEnv::setupLogger();
7070
auto run_mode = DB::PageStorageRunMode::ONLY_V3;
7171
DB::tests::TiFlashTestEnv::initializeGlobalContext(/*testdata_path*/ {}, run_mode);
72-
7372
DB::ServerInfo server_info;
7473
// `DMFileReaderPool` should be constructed before and destructed after `SegmentReaderPoolManager`.
7574
DB::DM::DMFileReaderPool::instance();

0 commit comments

Comments
 (0)