[feature] (memory) Switch TLS mem tracker to separate more detailed memory usage (#8605)
In pr #8476, all memory usage of a process is recorded in the process mem tracker, and all memory usage of a query is recorded in the query mem tracker, and it is still necessary to manually call `transfer to` to track the cached memory size. We hope to separate out more detailed memory usage based on Hook TCMalloc new/delete + TLS mem tracker. In this pr, the more detailed mem tracker is switched to TLS, which automatically and accurately counts more detailed memory usage than before.
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
#include "gen_cpp/PlanNodes_types.h"
|
||||
#include "runtime/row_batch.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "runtime/thread_context.h"
|
||||
#include "util/debug_util.h"
|
||||
#include "util/runtime_profile.h"
|
||||
|
||||
@ -52,6 +53,7 @@ Status CrossJoinNode::close(RuntimeState* state) {
|
||||
Status CrossJoinNode::construct_build_side(RuntimeState* state) {
|
||||
// Do a full scan of child(1) and store all build row batches.
|
||||
RETURN_IF_ERROR(child(1)->open(state));
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("Cross join, while getting next from child 1");
|
||||
|
||||
while (true) {
|
||||
RowBatch* batch =
|
||||
@ -63,9 +65,6 @@ Status CrossJoinNode::construct_build_side(RuntimeState* state) {
|
||||
bool eos = false;
|
||||
RETURN_IF_ERROR(child(1)->get_next(state, batch, &eos));
|
||||
|
||||
// to prevent use too many memory
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, "Cross join, while getting next from the child 1.");
|
||||
|
||||
SCOPED_TIMER(_build_timer);
|
||||
_build_batches.add_row_batch(batch);
|
||||
VLOG_ROW << build_list_debug_string();
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "exprs/expr.h"
|
||||
#include "runtime/row_batch.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "runtime/thread_context.h"
|
||||
|
||||
namespace doris {
|
||||
ExceptNode::ExceptNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs)
|
||||
@ -40,6 +41,7 @@ Status ExceptNode::init(const TPlanNode& tnode, RuntimeState* state) {
|
||||
|
||||
Status ExceptNode::open(RuntimeState* state) {
|
||||
RETURN_IF_ERROR(SetOperationNode::open(state));
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("Except Node, while probing the hash table.");
|
||||
// if a table is empty, the result must be empty
|
||||
if (_hash_tbl->size() == 0) {
|
||||
_hash_tbl_iterator = _hash_tbl->begin();
|
||||
@ -62,7 +64,6 @@ Status ExceptNode::open(RuntimeState* state) {
|
||||
while (!eos) {
|
||||
RETURN_IF_CANCELLED(state);
|
||||
RETURN_IF_ERROR(child(i)->get_next(state, _probe_batch.get(), &eos));
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, " Except , while probing the hash table.");
|
||||
for (int j = 0; j < _probe_batch->num_rows(); ++j) {
|
||||
_hash_tbl_iterator = _hash_tbl->find(_probe_batch->get_row(j));
|
||||
if (_hash_tbl_iterator != _hash_tbl->end()) {
|
||||
|
||||
@ -57,6 +57,7 @@
|
||||
#include "runtime/mem_tracker.h"
|
||||
#include "runtime/row_batch.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "runtime/thread_context.h"
|
||||
#include "util/debug_util.h"
|
||||
#include "util/runtime_profile.h"
|
||||
#include "vec/core/block.h"
|
||||
@ -208,6 +209,7 @@ Status ExecNode::prepare(RuntimeState* state) {
|
||||
_mem_tracker = MemTracker::create_tracker(-1, "ExecNode:" + _runtime_profile->name(),
|
||||
state->instance_mem_tracker(),
|
||||
MemTrackerLevel::VERBOSE, _runtime_profile.get());
|
||||
SCOPED_SWITCH_TASK_THREAD_LOCAL_MEM_TRACKER(_mem_tracker);
|
||||
_expr_mem_tracker = MemTracker::create_tracker(-1, "ExecNode:Exprs:" + _runtime_profile->name(),
|
||||
_mem_tracker);
|
||||
|
||||
@ -226,6 +228,7 @@ Status ExecNode::prepare(RuntimeState* state) {
|
||||
}
|
||||
|
||||
Status ExecNode::open(RuntimeState* state) {
|
||||
SCOPED_SWITCH_TASK_THREAD_LOCAL_MEM_TRACKER(_mem_tracker);
|
||||
RETURN_IF_ERROR(exec_debug_action(TExecNodePhase::OPEN));
|
||||
if (_vconjunct_ctx_ptr) {
|
||||
RETURN_IF_ERROR((*_vconjunct_ctx_ptr)->open(state));
|
||||
|
||||
@ -186,6 +186,7 @@ Status HashJoinNode::construct_hash_table(RuntimeState* state) {
|
||||
// The hash join node needs to keep in memory all build tuples, including the tuple
|
||||
// row ptrs. The row ptrs are copied into the hash table's internal structure so they
|
||||
// don't need to be stored in the _build_pool.
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("Hash join, while constructing the hash table.");
|
||||
RowBatch build_batch(child(1)->row_desc(), state->batch_size());
|
||||
RETURN_IF_ERROR(child(1)->open(state));
|
||||
|
||||
@ -303,7 +304,7 @@ Status HashJoinNode::get_next(RuntimeState* state, RowBatch* out_batch, bool* eo
|
||||
// In most cases, no additional memory overhead will be applied for at this stage,
|
||||
// but if the expression calculation in this node needs to apply for additional memory,
|
||||
// it may cause the memory to exceed the limit.
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, "Hash join, while execute get_next.");
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("Hash join, while execute get_next.");
|
||||
SCOPED_TIMER(_runtime_profile->total_time_counter());
|
||||
|
||||
if (reached_limit()) {
|
||||
@ -771,11 +772,9 @@ Status HashJoinNode::process_build_batch(RuntimeState* state, RowBatch* build_ba
|
||||
_build_pool.get(), false);
|
||||
}
|
||||
}
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, "Hash join, while constructing the hash table.");
|
||||
} else {
|
||||
// take ownership of tuple data of build_batch
|
||||
_build_pool->acquire_data(build_batch->tuple_data_pool(), false);
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, "Hash join, while constructing the hash table.");
|
||||
RETURN_IF_ERROR(_hash_tbl->resize_buckets_ahead(build_batch->num_rows()));
|
||||
for (int i = 0; i < build_batch->num_rows(); ++i) {
|
||||
_hash_tbl->insert_without_check(build_batch->get_row(i));
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "exprs/expr.h"
|
||||
#include "runtime/row_batch.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "runtime/thread_context.h"
|
||||
|
||||
namespace doris {
|
||||
IntersectNode::IntersectNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs)
|
||||
@ -44,6 +45,7 @@ Status IntersectNode::init(const TPlanNode& tnode, RuntimeState* state) {
|
||||
// repeat [2] this for all the rest child
|
||||
Status IntersectNode::open(RuntimeState* state) {
|
||||
RETURN_IF_ERROR(SetOperationNode::open(state));
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("Intersect Node, while probing the hash table.");
|
||||
// if a table is empty, the result must be empty
|
||||
if (_hash_tbl->size() == 0) {
|
||||
_hash_tbl_iterator = _hash_tbl->begin();
|
||||
@ -66,7 +68,6 @@ Status IntersectNode::open(RuntimeState* state) {
|
||||
while (!eos) {
|
||||
RETURN_IF_CANCELLED(state);
|
||||
RETURN_IF_ERROR(child(i)->get_next(state, _probe_batch.get(), &eos));
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, " Intersect , while probing the hash table.");
|
||||
for (int j = 0; j < _probe_batch->num_rows(); ++j) {
|
||||
_hash_tbl_iterator = _hash_tbl->find(_probe_batch->get_row(j));
|
||||
if (_hash_tbl_iterator != _hash_tbl->end()) {
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "runtime/raw_value.h"
|
||||
#include "runtime/row_batch.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "runtime/thread_context.h"
|
||||
|
||||
namespace doris {
|
||||
SetOperationNode::SetOperationNode(ObjectPool* pool, const TPlanNode& tnode,
|
||||
@ -137,6 +138,7 @@ bool SetOperationNode::equals(TupleRow* row, TupleRow* other) {
|
||||
Status SetOperationNode::open(RuntimeState* state) {
|
||||
RETURN_IF_ERROR(ExecNode::open(state));
|
||||
RETURN_IF_ERROR(exec_debug_action(TExecNodePhase::OPEN));
|
||||
SCOPED_SWITCH_THREAD_LOCAL_MEM_TRACKER_ERR_CB("SetOperation, while constructing the hash table.");
|
||||
SCOPED_TIMER(_runtime_profile->total_time_counter());
|
||||
RETURN_IF_CANCELLED(state);
|
||||
// open result expr lists.
|
||||
@ -156,7 +158,6 @@ Status SetOperationNode::open(RuntimeState* state) {
|
||||
RETURN_IF_ERROR(child(0)->get_next(state, &build_batch, &eos));
|
||||
// take ownership of tuple data of build_batch
|
||||
_build_pool->acquire_data(build_batch.tuple_data_pool(), false);
|
||||
RETURN_IF_INSTANCE_LIMIT_EXCEEDED(state, " SetOperation, while constructing the hash table.");
|
||||
// build hash table and remove duplicate items
|
||||
RETURN_IF_ERROR(_hash_tbl->resize_buckets_ahead(build_batch.num_rows()));
|
||||
for (int i = 0; i < build_batch.num_rows(); ++i) {
|
||||
|
||||
Reference in New Issue
Block a user