blob: 3d23bd447c19a55bb8ee824636250b6a7a697762 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// This file is copied from
// https://github.com/apache/impala/blob/branch-2.9.0/be/src/runtime/mem-tracker.cpp
// and modified by Doris
#include "runtime/memory/mem_tracker.h"
#include <fmt/format.h>
#include <mutex>
#include "bvar/bvar.h"
#include "runtime/memory/mem_tracker_limiter.h"
#include "runtime/thread_context.h"
namespace doris {
bvar::Adder<int64_t> g_memtracker_cnt("memtracker_cnt");
// Save all MemTrackers in use to maintain the weak relationship between MemTracker and MemTrackerLimiter.
// When MemTrackerLimiter prints statistics, all MemTracker statistics with weak relationship will be printed together.
// Each group corresponds to several MemTrackerLimiters and has a lock.
// Multiple groups are used to reduce the impact of locks.
std::vector<MemTracker::TrackerGroup> MemTracker::mem_tracker_pool(1000);
MemTracker::MemTracker(const std::string& label, MemTrackerLimiter* parent) : _label(label) {
_consumption = std::make_shared<MemCounter>();
bind_parent(parent);
}
void MemTracker::bind_parent(MemTrackerLimiter* parent) {
if (parent) {
_parent_label = parent->label();
_parent_group_num = parent->group_num();
} else if (is_thread_context_init()) {
_parent_label = thread_context()->thread_mem_tracker()->label();
_parent_group_num = thread_context()->thread_mem_tracker()->group_num();
}
{
std::lock_guard<std::mutex> l(mem_tracker_pool[_parent_group_num].group_lock);
_tracker_group_it = mem_tracker_pool[_parent_group_num].trackers.insert(
mem_tracker_pool[_parent_group_num].trackers.end(), this);
}
g_memtracker_cnt << 1;
}
MemTracker::~MemTracker() {
if (_parent_group_num != -1) {
std::lock_guard<std::mutex> l(mem_tracker_pool[_parent_group_num].group_lock);
if (_tracker_group_it != mem_tracker_pool[_parent_group_num].trackers.end()) {
mem_tracker_pool[_parent_group_num].trackers.erase(_tracker_group_it);
_tracker_group_it = mem_tracker_pool[_parent_group_num].trackers.end();
}
g_memtracker_cnt << -1;
}
}
MemTracker::Snapshot MemTracker::make_snapshot() const {
Snapshot snapshot;
snapshot.label = _label;
snapshot.parent_label = _parent_label;
snapshot.limit = -1;
snapshot.cur_consumption = _consumption->current_value();
snapshot.peak_consumption = _consumption->peak_value();
return snapshot;
}
void MemTracker::make_group_snapshot(std::vector<MemTracker::Snapshot>* snapshots,
int64_t group_num, std::string parent_label) {
std::lock_guard<std::mutex> l(mem_tracker_pool[group_num].group_lock);
for (auto tracker : mem_tracker_pool[group_num].trackers) {
if (tracker->parent_label() == parent_label && tracker->peak_consumption() != 0) {
snapshots->push_back(tracker->make_snapshot());
}
}
}
std::string MemTracker::log_usage(MemTracker::Snapshot snapshot) {
return fmt::format("MemTracker Label={}, Parent Label={}, Used={}({} B), Peak={}({} B)",
snapshot.label, snapshot.parent_label, print_bytes(snapshot.cur_consumption),
snapshot.cur_consumption, print_bytes(snapshot.peak_consumption),
snapshot.peak_consumption);
}
} // namespace doris