This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 6ef6140f737 [fix](load) fix load memory usage is more than branch-3.1
(#61173)
6ef6140f737 is described below
commit 6ef6140f737478ba2155dbcec4c4200d0b4064fa
Author: TengJianPing <[email protected]>
AuthorDate: Thu Mar 12 22:09:23 2026 +0800
[fix](load) fix load memory usage is more than branch-3.1 (#61173)
### What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [ ] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
be/src/olap/memtable_flush_executor.cpp | 18 +-
be/src/olap/memtable_memory_limiter.cpp | 3 +-
be/src/vec/common/allocator.h | 6 -
be/src/vec/common/pod_array.h | 175 ++++---------------
be/src/vec/common/pod_array_fwd.h | 13 +-
be/test/vec/common/pod_array_test.cpp | 288 --------------------------------
6 files changed, 46 insertions(+), 457 deletions(-)
diff --git a/be/src/olap/memtable_flush_executor.cpp
b/be/src/olap/memtable_flush_executor.cpp
index f2c2b764644..3900a42f806 100644
--- a/be/src/olap/memtable_flush_executor.cpp
+++ b/be/src/olap/memtable_flush_executor.cpp
@@ -194,17 +194,17 @@ Status FlushToken::_do_flush_memtable(MemTable* memtable,
int32_t segment_id, in
memtable->resource_ctx()->memory_context()->mem_tracker()->write_tracker());
SCOPED_CONSUME_MEM_TRACKER(memtable->mem_tracker());
- DEFER_RELEASE_RESERVED();
+ // DEFER_RELEASE_RESERVED();
- auto reserve_size = memtable->get_flush_reserve_memory_size();
- if
(memtable->resource_ctx()->task_controller()->is_enable_reserve_memory() &&
- reserve_size > 0) {
- RETURN_IF_ERROR(_try_reserve_memory(memtable->resource_ctx(),
reserve_size));
- }
+ // auto reserve_size = memtable->get_flush_reserve_memory_size();
+ // if
(memtable->resource_ctx()->task_controller()->is_enable_reserve_memory() &&
+ // reserve_size > 0) {
+ // RETURN_IF_ERROR(_try_reserve_memory(memtable->resource_ctx(),
reserve_size));
+ // }
- Defer defer {[&]() {
-
ExecEnv::GetInstance()->storage_engine().memtable_flush_executor()->dec_flushing_task();
- }};
+ // Defer defer {[&]() {
+ //
ExecEnv::GetInstance()->storage_engine().memtable_flush_executor()->dec_flushing_task();
+ // }};
std::unique_ptr<vectorized::Block> block;
RETURN_IF_ERROR(memtable->to_block(&block));
RETURN_IF_ERROR(_rowset_writer->flush_memtable(block.get(),
segment_id, flush_size));
diff --git a/be/src/olap/memtable_memory_limiter.cpp
b/be/src/olap/memtable_memory_limiter.cpp
index 67c70b4b3f3..fbe4c392956 100644
--- a/be/src/olap/memtable_memory_limiter.cpp
+++ b/be/src/olap/memtable_memory_limiter.cpp
@@ -316,7 +316,8 @@ void MemTableMemoryLimiter::_refresh_mem_tracker() {
g_memtable_write_memory.set_value(_queue_mem_usage);
g_memtable_flush_memory.set_value(_flush_mem_usage);
g_memtable_load_memory.set_value(_mem_usage);
- VLOG_DEBUG << "refreshed mem_tracker, num writers: " << _writers.size();
+ VLOG_DEBUG << "refreshed mem_tracker, num writers: " << _writers.size()
+ << ", mem usage: " << _mem_usage;
_mem_tracker->set_consumption(_mem_usage);
if (!_hard_limit_reached()) {
_hard_limit_end_cond.notify_all();
diff --git a/be/src/vec/common/allocator.h b/be/src/vec/common/allocator.h
index e7ede2adfa9..58bc9a6089d 100644
--- a/be/src/vec/common/allocator.h
+++ b/be/src/vec/common/allocator.h
@@ -240,8 +240,6 @@ public:
bool memory_tracker_exceed(size_t size, std::string* err_msg) const;
- static constexpr bool need_check_and_tracking_memory() { return
check_and_tracking_memory; }
-
protected:
static constexpr size_t get_stack_threshold() { return 0; }
@@ -333,10 +331,6 @@ public:
return Base::memory_tracker_exceed(size, err_msg);
}
- static constexpr bool need_check_and_tracking_memory() {
- return Base::need_check_and_tracking_memory();
- }
-
protected:
static constexpr size_t get_stack_threshold() { return N; }
};
diff --git a/be/src/vec/common/pod_array.h b/be/src/vec/common/pod_array.h
index 99702eb7ed8..00d794b2724 100644
--- a/be/src/vec/common/pod_array.h
+++ b/be/src/vec/common/pod_array.h
@@ -87,9 +87,7 @@ inline size_t round_up_to_power_of_two_or_zero(size_t n) {
*
* 16 bytes 512 bytes 3553 bytes
15 bytes
* pad_left ----- c_start -------------c_end ----------------------------
c_end_of_storage ------------- pad_right
- * ^ ^
^
- * | |
|
- * | c_res_mem (>= c_end && <=
c_end_of_storage) |
+ * ^
^
* |
|
* +-------------------------------------- allocated_bytes (4096 bytes)
-----------------------------------+
*
@@ -109,7 +107,6 @@ inline size_t round_up_to_power_of_two_or_zero(size_t n) {
* TODO Allow greater alignment than alignof(T). Example: array of char
aligned to page size.
*/
static constexpr size_t EmptyPODArraySize = 1024;
-static constexpr size_t TrackingGrowthMinSize = (1ULL << 18); // 256K
extern const char empty_pod_array[EmptyPODArraySize];
/** Base class that depend only on size of element, not on element itself.
@@ -134,7 +131,6 @@ protected:
char* c_start = null; /// Does not include pad_left.
char* c_end = null;
char* c_end_of_storage = null; /// Does not include pad_right.
- char* c_res_mem = null;
/// The amount of memory occupied by the num_elements of the elements.
static size_t byte_size(size_t num_elements) {
@@ -156,77 +152,6 @@ protected:
return byte_size(num_elements) + pad_right + pad_left;
}
- inline void check_memory(int64_t size) {
- std::string err_msg;
- if (TAllocator::sys_memory_exceed(size, &err_msg) ||
- TAllocator::memory_tracker_exceed(size, &err_msg)) {
- err_msg = fmt::format("PODArray reserve memory failed, {}.",
err_msg);
- if (doris::enable_thread_catch_bad_alloc) {
- LOG(WARNING) << err_msg;
- throw doris::Exception(doris::ErrorCode::MEM_ALLOC_FAILED,
err_msg);
- } else {
- LOG_EVERY_N(WARNING, 1024) << err_msg;
- }
- }
- }
-
- inline void reset_resident_memory_impl(const char* c_end_new) {
- static_assert(!TAllocator::need_check_and_tracking_memory(),
- "TAllocator should `check_and_tracking_memory` is
false");
- // Premise conditions:
- // - c_res_mem <= c_end_of_storage
- // - c_end_new > c_res_mem
- // - If padding is not a power of 2, such as 24, allocated_bytes()
will also not be a power of 2.
- //
- // If allocated_bytes <= 256K, res_mem_growth = c_end_of_storage -
c_res_mem.
- //
- // If capacity >= 512K:
- // - If `c_end_of_storage - c_res_mem < TrackingGrowthMinSize`,
then tracking to c_end_of_storage.
- // - `c_end_new - c_res_mem` is the size of the physical memory
growth,
- // which is also the minimum tracking size of this time,
- // `(((c_end_new - c_res_mem) >> 16) << 16)` is aligned down to
64K,
- // assuming `allocated_bytes >= 512K`, so `(allocated_bytes >>
3)` is at least 64K,
- // so `(((c_end_new - c_res_mem) >> 16) << 16) +
(allocated_bytes() >> 3)`
- // must be greater than `c_end_new - c_res_mem`.
- //
- // For example:
- // - 256K < capacity <= 512K,
- // it will only tracking twice,
- // the second time `c_end_of_storage - c_res_mem <
TrackingGrowthMinSize` is true,
- // so it will tracking to c_end_of_storage.
- // - capacity > 32M, `(((c_end_new - c_res_mem) >> 16) << 16)`
align the increased
- // physical memory size down to 64k, then add
`(allocated_bytes() >> 3)` equals 2M,
- // so `reset_resident_memory` is tracking an additional 2M,
- // after that, physical memory growth within 2M does not
need to reset_resident_memory again.
- //
- // so, when PODArray is expanded by power of 2,
- // the memory is checked and tracked up to 8 times between each
expansion,
- // because each time additional tracking `(allocated_bytes() >> 3)`.
- // after each reset_resident_memory, tracking_res_memory >= used_bytes;
- int64_t res_mem_growth =
- c_end_of_storage - c_res_mem < TrackingGrowthMinSize
- ? c_end_of_storage - c_res_mem
- : std::min(static_cast<size_t>(c_end_of_storage -
c_res_mem),
- static_cast<size_t>((((c_end_new -
c_res_mem) >> 16) << 16) +
- (allocated_bytes() >>
3)));
- DCHECK(res_mem_growth > 0) << ", c_end_new: " << (c_end_new - c_start)
- << ", c_res_mem: " << (c_res_mem - c_start)
- << ", c_end_of_storage: " <<
(c_end_of_storage - c_start)
- << ", allocated_bytes: " <<
allocated_bytes()
- << ", res_mem_growth: " << res_mem_growth;
- check_memory(res_mem_growth);
- CONSUME_THREAD_MEM_TRACKER(res_mem_growth);
- c_res_mem = c_res_mem + res_mem_growth;
- }
-
- inline void reset_resident_memory(const char* c_end_new) {
- if (UNLIKELY(c_end_new > c_res_mem)) {
- reset_resident_memory_impl(c_end_new);
- }
- }
-
- inline void reset_resident_memory() { reset_resident_memory(c_end); }
-
void alloc_for_num_elements(size_t num_elements) {
alloc(round_up_to_power_of_two_or_zero(minimum_memory_for_elements(num_elements)));
}
@@ -238,17 +163,16 @@ protected:
c_start = allocated + pad_left;
c_end = c_start;
- c_res_mem = c_start;
c_end_of_storage = allocated + bytes - pad_right;
- CONSUME_THREAD_MEM_TRACKER(pad_left + pad_right);
if (pad_left) memset(c_start - ELEMENT_SIZE, 0, ELEMENT_SIZE);
}
void dealloc() {
if (c_start == null) return;
+
unprotect();
- RELEASE_THREAD_MEM_TRACKER((c_res_mem - c_start + pad_right +
pad_left));
+
TAllocator::free(c_start - pad_left, allocated_bytes());
}
@@ -262,21 +186,13 @@ protected:
unprotect();
ptrdiff_t end_diff = c_end - c_start;
- ptrdiff_t res_mem_diff = c_res_mem - c_start;
-
- // Realloc can do 2 possible things:
- // - expand existing memory region
- // - allocate new memory block and free the old one
- // Because we don't know which option will be picked we need to make
sure there is enough
- // memory for all options.
- check_memory(res_mem_diff);
+
char* allocated = reinterpret_cast<char*>(
TAllocator::realloc(c_start - pad_left, allocated_bytes(),
bytes,
std::forward<TAllocatorParams>(allocator_params)...));
c_start = allocated + pad_left;
c_end = c_start + end_diff;
- c_res_mem = c_start + res_mem_diff;
c_end_of_storage = allocated + bytes - pad_right;
}
@@ -352,26 +268,10 @@ public:
resize_assume_reserved(n);
}
- void resize_assume_reserved(const size_t n) {
- c_end = c_start + byte_size(n);
- reset_resident_memory();
- }
+ void resize_assume_reserved(const size_t n) { c_end = c_start +
byte_size(n); }
const char* raw_data() const { return c_start; }
- template <typename... TAllocatorParams>
- void push_back_raw(const char* ptr, TAllocatorParams&&...
allocator_params) {
- if (UNLIKELY(c_end + ELEMENT_SIZE > c_res_mem)) { // c_res_mem <=
c_end_of_storage
- if (UNLIKELY(c_end + ELEMENT_SIZE > c_end_of_storage)) {
-
reserve_for_next_size(std::forward<TAllocatorParams>(allocator_params)...);
- }
- reset_resident_memory_impl(c_end + ELEMENT_SIZE);
- }
-
- memcpy(c_end, ptr, ELEMENT_SIZE);
- c_end += byte_size(1);
- }
-
void protect() {
#ifndef NDEBUG
protect_impl(PROT_READ);
@@ -433,7 +333,6 @@ public:
PODArray(size_t n) {
this->alloc_for_num_elements(n);
this->c_end += this->byte_size(n);
- this->reset_resident_memory();
}
PODArray(size_t n, const T& x) {
@@ -489,48 +388,57 @@ public:
/// Same as resize, but zeroes new elements.
void resize_fill(size_t n) {
size_t old_size = this->size();
- const auto new_size = this->byte_size(n);
if (n > old_size) {
this->reserve(n);
- this->reset_resident_memory(this->c_start + new_size);
memset(this->c_end, 0, this->byte_size(n - old_size));
}
- this->c_end = this->c_start + new_size;
+ this->c_end = this->c_start + this->byte_size(n);
}
- /// reset the array capacity
- /// fill the new additional elements using the value
void resize_fill(size_t n, const T& value) {
size_t old_size = this->size();
- const auto new_size = this->byte_size(n);
if (n > old_size) {
this->reserve(n);
- this->reset_resident_memory(this->c_start + new_size);
std::fill(t_end(), t_end() + n - old_size, value);
}
- this->c_end = this->c_start + new_size;
+ this->c_end = this->c_start + this->byte_size(n);
}
template <typename U, typename... TAllocatorParams>
void push_back(U&& x, TAllocatorParams&&... allocator_params) {
- if (UNLIKELY(this->c_end + sizeof(T) > this->c_res_mem)) { //
c_res_mem <= c_end_of_storage
- if (UNLIKELY(this->c_end + sizeof(T) > this->c_end_of_storage)) {
-
this->reserve_for_next_size(std::forward<TAllocatorParams>(allocator_params)...);
- }
- this->reset_resident_memory_impl(this->c_end + this->byte_size(1));
+ if (UNLIKELY(this->c_end + sizeof(T) > this->c_end_of_storage)) {
+
this->reserve_for_next_size(std::forward<TAllocatorParams>(allocator_params)...);
}
new (t_end()) T(std::forward<U>(x));
this->c_end += this->byte_size(1);
}
+ template <typename U, typename... TAllocatorParams>
+ void add_num_element(U&& x, uint32_t num, TAllocatorParams&&...
allocator_params) {
+ if (num != 0) {
+ const auto growth_size = this->byte_size(num);
+ if (UNLIKELY(this->c_end + growth_size > this->c_end_of_storage)) {
+ this->reserve(this->size() + num);
+ }
+ std::fill(t_end(), t_end() + num, x);
+ this->c_end = this->c_end + growth_size;
+ }
+ }
+
+ template <typename U, typename... TAllocatorParams>
+ void add_num_element_without_reserve(U&& x, uint32_t num,
+ TAllocatorParams&&...
allocator_params) {
+ std::fill(t_end(), t_end() + num, x);
+ this->c_end += sizeof(T) * num;
+ }
+
/**
* you must make sure to reserve podarray before calling this method
* remove branch if can improve performance
*/
template <typename U, typename... TAllocatorParams>
void push_back_without_reserve(U&& x, TAllocatorParams&&...
allocator_params) {
- this->reset_resident_memory(this->c_end + this->byte_size(1));
new (t_end()) T(std::forward<U>(x));
this->c_end += this->byte_size(1);
}
@@ -540,11 +448,8 @@ public:
*/
template <typename... Args>
void emplace_back(Args&&... args) {
- if (UNLIKELY(this->c_end + sizeof(T) > this->c_res_mem)) { //
c_res_mem <= c_end_of_storage
- if (UNLIKELY(this->c_end + sizeof(T) > this->c_end_of_storage)) {
- this->reserve_for_next_size();
- }
- this->reset_resident_memory_impl(this->c_end + this->byte_size(1));
+ if (UNLIKELY(this->c_end + sizeof(T) > this->c_end_of_storage)) {
+ this->reserve_for_next_size();
}
new (t_end()) T(std::forward<Args>(args)...);
@@ -583,7 +488,6 @@ public:
static_assert(pad_right_ >= 15);
insert_prepare(from_begin, from_end,
std::forward<TAllocatorParams>(allocator_params)...);
size_t bytes_to_copy = this->byte_size(from_end - from_begin);
- this->reset_resident_memory(this->c_end + bytes_to_copy);
memcpy_small_allow_read_write_overflow15(
this->c_end, reinterpret_cast<const void*>(&*from_begin),
bytes_to_copy);
this->c_end += bytes_to_copy;
@@ -597,7 +501,6 @@ public:
}
size_t bytes_to_move = this->byte_size(end() - it);
insert_prepare(from_begin, from_end);
- this->reset_resident_memory(this->c_end + bytes_to_copy);
if (UNLIKELY(bytes_to_move)) {
memmove(this->c_end + bytes_to_copy - bytes_to_move, this->c_end -
bytes_to_move,
@@ -613,7 +516,6 @@ public:
void insert_assume_reserved(It1 from_begin, It2 from_end) {
this->assert_not_intersects(from_begin, from_end);
size_t bytes_to_copy = this->byte_size(from_end - from_begin);
- this->reset_resident_memory(this->c_end + bytes_to_copy);
memcpy(this->c_end, reinterpret_cast<const void*>(&*from_begin),
bytes_to_copy);
this->c_end += bytes_to_copy;
}
@@ -621,7 +523,6 @@ public:
template <typename It1, typename It2>
void insert_assume_reserved_and_allow_overflow(It1 from_begin, It2
from_end) {
size_t bytes_to_copy = this->byte_size(from_end - from_begin);
- this->reset_resident_memory(this->c_end + bytes_to_copy);
memcpy_small_allow_read_write_overflow15(
this->c_end, reinterpret_cast<const void*>(&*from_begin),
bytes_to_copy);
this->c_end += bytes_to_copy;
@@ -642,11 +543,9 @@ public:
auto swap_stack_heap = [this](PODArray& arr1, PODArray& arr2) {
size_t stack_size = arr1.size();
size_t stack_allocated = arr1.allocated_bytes();
- size_t stack_res_mem_used = arr1.c_res_mem - arr1.c_start;
size_t heap_size = arr2.size();
size_t heap_allocated = arr2.allocated_bytes();
- size_t heap_res_mem_used = arr2.c_res_mem - arr2.c_start;
/// Keep track of the stack content we have to copy.
char* stack_c_start = arr1.c_start;
@@ -655,14 +554,12 @@ public:
arr1.c_start = arr2.c_start;
arr1.c_end_of_storage = arr1.c_start + heap_allocated -
arr2.pad_right - arr2.pad_left;
arr1.c_end = arr1.c_start + this->byte_size(heap_size);
- arr1.c_res_mem = arr1.c_start + heap_res_mem_used;
/// Allocate stack space for arr2.
arr2.alloc(stack_allocated);
/// Copy the stack content.
memcpy(arr2.c_start, stack_c_start, this->byte_size(stack_size));
arr2.c_end = arr2.c_start + this->byte_size(stack_size);
- arr2.c_res_mem = arr2.c_start + stack_res_mem_used;
};
auto do_move = [this](PODArray& src, PODArray& dest) {
@@ -671,17 +568,14 @@ public:
dest.alloc(src.allocated_bytes());
memcpy(dest.c_start, src.c_start, this->byte_size(src.size()));
dest.c_end = dest.c_start + this->byte_size(src.size());
- dest.c_res_mem = dest.c_start + (src.c_res_mem - src.c_start);
src.c_start = Base::null;
src.c_end = Base::null;
src.c_end_of_storage = Base::null;
- src.c_res_mem = Base::null;
} else {
std::swap(dest.c_start, src.c_start);
std::swap(dest.c_end, src.c_end);
std::swap(dest.c_end_of_storage, src.c_end_of_storage);
- std::swap(dest.c_res_mem, src.c_res_mem);
}
};
@@ -709,11 +603,9 @@ public:
size_t lhs_size = this->size();
size_t lhs_allocated = this->allocated_bytes();
- size_t lhs_res_mem_used = this->c_res_mem - this->c_start;
size_t rhs_size = rhs.size();
size_t rhs_allocated = rhs.allocated_bytes();
- size_t rhs_res_mem_used = rhs.c_res_mem - rhs.c_start;
this->c_end_of_storage =
this->c_start + rhs_allocated - Base::pad_right -
Base::pad_left;
@@ -721,9 +613,6 @@ public:
this->c_end = this->c_start + this->byte_size(rhs_size);
rhs.c_end = rhs.c_start + this->byte_size(lhs_size);
-
- this->c_res_mem = this->c_start + rhs_res_mem_used;
- rhs.c_res_mem = rhs.c_start + lhs_res_mem_used;
} else if (this->is_allocated_from_stack() &&
!rhs.is_allocated_from_stack()) {
swap_stack_heap(*this, rhs);
} else if (!this->is_allocated_from_stack() &&
rhs.is_allocated_from_stack()) {
@@ -732,12 +621,9 @@ public:
std::swap(this->c_start, rhs.c_start);
std::swap(this->c_end, rhs.c_end);
std::swap(this->c_end_of_storage, rhs.c_end_of_storage);
- std::swap(this->c_res_mem, rhs.c_res_mem);
}
}
- /// reset the array capacity
- /// replace the all elements using the value
void assign(size_t n, const T& x) {
this->resize(n);
std::fill(begin(), end(), x);
@@ -751,7 +637,6 @@ public:
this->reserve(round_up_to_power_of_two_or_zero(required_capacity));
size_t bytes_to_copy = this->byte_size(required_capacity);
- this->reset_resident_memory(this->c_start + bytes_to_copy);
memcpy(this->c_start, reinterpret_cast<const void*>(&*from_begin),
bytes_to_copy);
this->c_end = this->c_start + bytes_to_copy;
}
diff --git a/be/src/vec/common/pod_array_fwd.h
b/be/src/vec/common/pod_array_fwd.h
index 5fc62c23fa0..bd0c7e272e4 100644
--- a/be/src/vec/common/pod_array_fwd.h
+++ b/be/src/vec/common/pod_array_fwd.h
@@ -32,8 +32,7 @@ inline constexpr size_t integerRoundUp(size_t value, size_t
dividend) {
return ((value + dividend - 1) / dividend) * dividend;
}
-template <typename T, size_t initial_bytes = 4096,
- typename TAllocator = Allocator<false, false, false,
DefaultMemoryAllocator, false>,
+template <typename T, size_t initial_bytes = 4096, typename TAllocator =
Allocator<false>,
size_t pad_right_ = 0, size_t pad_left_ = 0>
class PODArray;
@@ -41,8 +40,7 @@ class PODArray;
* TODO, Adapt internal data structures to 512-bit era
https://github.com/ClickHouse/ClickHouse/pull/42564
* Padding in internal data structures increased to 64 bytes., support
AVX-512 simd.
*/
-template <typename T, size_t initial_bytes = 4096,
- typename TAllocator = Allocator<false, false, false,
DefaultMemoryAllocator, false>>
+template <typename T, size_t initial_bytes = 4096, typename TAllocator =
Allocator<false>>
using PaddedPODArray = PODArray<T, initial_bytes, TAllocator, 16, 15>;
/** A helper for declaring PODArray that uses inline memory.
@@ -51,9 +49,8 @@ using PaddedPODArray = PODArray<T, initial_bytes, TAllocator,
16, 15>;
*/
template <typename T, size_t inline_bytes,
size_t rounded_bytes = integerRoundUp(inline_bytes, sizeof(T))>
-using PODArrayWithStackMemory = PODArray<
- T, rounded_bytes,
- AllocatorWithStackMemory<Allocator<false, false, false,
DefaultMemoryAllocator, false>,
- rounded_bytes, alignof(T)>>;
+using PODArrayWithStackMemory =
+ PODArray<T, rounded_bytes,
+ AllocatorWithStackMemory<Allocator<false>, rounded_bytes,
alignof(T)>>;
} // namespace doris::vectorized
diff --git a/be/test/vec/common/pod_array_test.cpp
b/be/test/vec/common/pod_array_test.cpp
index 5dee0ff8c93..81f7ed1ded8 100644
--- a/be/test/vec/common/pod_array_test.cpp
+++ b/be/test/vec/common/pod_array_test.cpp
@@ -634,292 +634,4 @@ TEST(PODArrayTest, PODErase) {
}
}
-TEST(PODArrayTest, PaddedPODArrayTrackingMemory) {
- auto t = MemTrackerLimiter::create_shared(MemTrackerLimiter::Type::GLOBAL,
"UT");
- // PaddedPODArray
- {
- SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(t);
- EXPECT_EQ(t->consumption(), 0);
- size_t PRE_GROWTH_SIZE = vectorized::TrackingGrowthMinSize;
-
- vectorized::PaddedPODArray<uint64_t, 4096> array;
- EXPECT_EQ(t->consumption(), 0);
- int64_t mem_consumption = t->consumption();
- size_t c_res_mem = 0;
-
- auto tracking_size = [&array, &c_res_mem](size_t c_end_new) {
- return (((c_end_new - c_res_mem) >> 16) << 16) +
(array.allocated_bytes() >> 3);
- };
-
- auto check_memory_growth = [&t, &mem_consumption, &c_res_mem](size_t
mem_growth) {
- EXPECT_EQ(t->consumption(), mem_consumption + mem_growth)
- << ", current: " << mem_consumption << ", c_res_mem: " <<
c_res_mem
- << ", mem_growth: " << mem_growth << ", expected: " <<
t->consumption() << ", "
- << get_stack_trace();
- std::cout << "PODArrayTest check_memory, current: " <<
mem_consumption
- << ", c_res_mem: " << c_res_mem << ", mem_growth: " <<
mem_growth
- << ", expected: " << t->consumption() << std::endl;
- mem_consumption += mem_growth;
- c_res_mem += mem_growth;
- };
-
- array.push_back(1);
- EXPECT_EQ(array.size(), 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 8, c_res_mem: 0, c_end_of_storage: 4064, res_mem_growth:
4064
- check_memory_growth(array.allocated_bytes());
-
- array.push_back(2);
- EXPECT_EQ(array.size(), 2);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t));
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t));
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 262144, c_res_mem: 4064, c_end_of_storage: 524256,
res_mem_growth: 262144
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE));
-
- array.push_back(3);
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.assign({1, 2, 3});
- EXPECT_EQ(array.size(), 3);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.resize((PRE_GROWTH_SIZE / sizeof(uint64_t)) * 3);
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 3);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 786432, c_res_mem: 266208, c_end_of_storage: 1048544,
res_mem_growth: 589824
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 3));
-
- array.push_back_without_reserve(11);
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 3 + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t) * 6, 2);
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 6);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 1572864, c_res_mem: 856032, c_end_of_storage: 2097120,
res_mem_growth: 917504
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 6));
-
- array.push_back_without_reserve(22);
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 6 + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.emplace_back(33);
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 6 + 2);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.pop_back();
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 6 + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- for (int i = 0; i < (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 2; i++) {
- array.push_back(2);
- array.pop_back();
- array.pop_back();
- }
- EXPECT_EQ(array.size(), (PRE_GROWTH_SIZE / sizeof(uint64_t)) * 4 + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t) * 7, 3);
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 7);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 1835008, c_res_mem: 1773536, c_end_of_storage: 2097120,
res_mem_growth: 262144,
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 7));
-
- {
- vectorized::PaddedPODArray<uint64_t, 32> array2;
- array2.push_back(3);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 8, c_res_mem: 0, c_end_of_storage: 8,
res_mem_growth: 8
- EXPECT_EQ(t->consumption(),
- mem_consumption + array2.allocated_bytes()); // 40 =
array2.allocated_bytes()
- array2.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t), 3);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 262144, c_res_mem: 8, c_end_of_storage: 524256,
res_mem_growth: 262144
- EXPECT_EQ(t->consumption(),
- mem_consumption + 40 +
- PRE_GROWTH_SIZE); // 40 + PRE_GROWTH_SIZE =
array2.c_res_mem
- array.insert(array2.begin(), array2.end());
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 2097152, c_res_mem: 2035680, c_end_of_storage:
4194272, res_mem_growth: 524288
- EXPECT_EQ(t->consumption(),
- mem_consumption + tracking_size(PRE_GROWTH_SIZE * 8) +
40 + PRE_GROWTH_SIZE);
- }
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 8);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 8)); // release
array2
-
- {
- vectorized::PaddedPODArray<uint64_t, 32> array2;
- array2.resize_fill((PRE_GROWTH_SIZE / sizeof(uint64_t)) * 7, 3);
- // c_end_new: 1835008, c_res_mem: 0, c_end_of_storage: 2097120,
res_mem_growth: 2097120
- array.insert_small_allow_read_write_overflow15(array2.begin(),
array2.end());
- // c_end_new: 3932160, c_res_mem: 2559968, c_end_of_storage:
4194272, res_mem_growth: 1634304
- }
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 15);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(
- array.allocated_bytes() -
- mem_consumption); // array.capacity >
tracking_size(PRE_GROWTH_SIZE * 15)
-
- {
- vectorized::PaddedPODArray<uint64_t, 32> array2;
- array2.push_back(3);
- array.insert(array2.begin(), array2.end());
- }
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 15 + 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t) * 16, 4);
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 16);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // c_end_new: 4194304, c_res_mem: 4194272, c_end_of_storage: 8388576,
res_mem_growth: 1048576
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 16));
-
- {
- vectorized::PaddedPODArray<uint64_t, 32> array2;
- array2.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t), 3);
- array.insert(array.begin(), array2.begin(), array2.end());
- }
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 17);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- {
- vectorized::PaddedPODArray<uint64_t, 32> array2;
- array2.resize_fill((PRE_GROWTH_SIZE / sizeof(uint64_t) * 2), 3);
- array.insert_assume_reserved(array2.begin(), array2.end());
- array.insert_assume_reserved_and_allow_overflow(array2.begin(),
array2.end());
- }
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 21);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(tracking_size(PRE_GROWTH_SIZE * 21));
-
- size_t n = 100;
- array.assign(n, (uint64_t)0);
- EXPECT_EQ(array.size(), 100);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
-
- array.erase(array.begin() + 10, array.end());
- EXPECT_EQ(array.size(), 10);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- check_memory_growth(0);
- }
- EXPECT_EQ(t->consumption(), 0);
-}
-
-TEST(PODArrayTest, PODArrayTrackingMemory) {
- auto t = MemTrackerLimiter::create_shared(MemTrackerLimiter::Type::GLOBAL,
"UT");
-
- // PODArray with AllocatorWithStackMemory
- {
- SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(t);
- EXPECT_EQ(t->consumption(), 0);
- size_t PRE_GROWTH_SIZE = vectorized::TrackingGrowthMinSize;
-
- static constexpr size_t initial_bytes = 32;
- using Array =
- vectorized::PODArray<uint64_t, initial_bytes,
- AllocatorWithStackMemory<Allocator<
- false, false, false,
DefaultMemoryAllocator, false>>>;
- Array array;
-
- array.push_back(1);
- EXPECT_EQ(array.size(), 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // reset_resident_memory, c_end_new: 8, c_res_mem: 0,
c_end_of_storage: 32, res_mem_growth: 32
- EXPECT_EQ(t->consumption(), array.allocated_bytes());
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t), 1);
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t));
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // reset_resident_memory, c_end_new: 262144, c_res_mem: 32,
c_end_of_storage: 262144, res_mem_growth: 262112
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE);
-
- // test swap
- size_t new_capacity = 0;
- size_t new_size = 0;
- {
- Array array2;
- array2.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t) * 2, 1);
- EXPECT_EQ(array2.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 2);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- // reset_resident_memory, c_end_new: 524288, c_res_mem: 0,
c_end_of_storage: 524288, res_mem_growth: 524288
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 3);
- new_capacity = array2.capacity();
- new_size = array2.size();
-
- array.swap(array2);
- EXPECT_EQ(array2.size(), PRE_GROWTH_SIZE / sizeof(uint64_t));
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 2);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 3);
- EXPECT_EQ(array.capacity(), new_capacity);
- EXPECT_EQ(array.size(), new_size);
- }
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 2);
- }
- EXPECT_EQ(t->consumption(), 0);
-
- // PODArray with Allocator
- {
- SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(t);
- EXPECT_EQ(t->consumption(), 0);
- static constexpr size_t PRE_GROWTH_SIZE = (1ULL << 20); // 1M
-
- static constexpr size_t initial_bytes = 32;
- using Array =
- vectorized::PODArray<uint64_t, initial_bytes,
- Allocator<false, false, false,
DefaultMemoryAllocator, false>>;
- Array array;
-
- array.push_back(1);
- EXPECT_EQ(array.size(), 1);
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), array.allocated_bytes());
-
- array.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t), 1);
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t));
- doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE);
-
- // test swap
- size_t new_capacity = 0;
- size_t new_size = 0;
- {
- Array array2;
- array2.resize_fill(PRE_GROWTH_SIZE / sizeof(uint64_t) * 2, 1);
- EXPECT_EQ(array2.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 2);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 3);
- new_capacity = array2.capacity();
- new_size = array2.size();
-
- array.swap(array2);
- EXPECT_EQ(array2.size(), PRE_GROWTH_SIZE / sizeof(uint64_t));
- EXPECT_EQ(array.size(), PRE_GROWTH_SIZE / sizeof(uint64_t) * 2);
-
doris::thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 3);
- EXPECT_EQ(array.capacity(), new_capacity);
- EXPECT_EQ(array.size(), new_size);
- }
- EXPECT_EQ(t->consumption(), PRE_GROWTH_SIZE * 2);
- }
- EXPECT_EQ(t->consumption(), 0);
-}
-
} // end namespace doris
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]