Coverage Report

Created: 2026-04-11 14:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/runtime/memory/mem_counter.h
Line
Count
Source
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
// This file is copied from
18
#pragma once
19
20
#include <atomic>
21
#include <cstdint>
22
#include <string>
23
24
#include "common/compiler_util.h"
25
#include "util/pretty_printer.h"
26
27
namespace doris {
28
29
/*
30
 * A counter that keeps track of the current and peak memory usage seen.
31
 * Relaxed ordering, not accurate in real time.
32
 *
33
 * This class is thread-safe.
34
*/
35
class MemCounter {
36
public:
37
49.8M
    MemCounter() = default;
38
39
77.7M
    void add(int64_t delta) {
40
77.7M
        if (UNLIKELY(delta == 0)) {
41
3.17M
            return;
42
3.17M
        }
43
74.6M
        int64_t value = _current_value.fetch_add(delta, std::memory_order_relaxed) + delta;
44
74.6M
        update_peak(value);
45
74.6M
    }
46
47
0
    void add_no_update_peak(int64_t delta) { // need extreme fast
48
0
        _current_value.fetch_add(delta, std::memory_order_relaxed);
49
0
    }
50
51
28.9M
    bool try_add(int64_t delta, int64_t max) {
52
28.9M
        if (UNLIKELY(delta == 0)) {
53
0
            return true;
54
0
        }
55
28.9M
        int64_t cur_val = _current_value.load(std::memory_order_relaxed);
56
28.9M
        int64_t new_val = 0;
57
28.9M
        do {
58
28.9M
            new_val = cur_val + delta;
59
28.9M
            if (UNLIKELY(new_val > max)) {
60
1
                return false;
61
1
            }
62
28.9M
        } while (UNLIKELY(!_current_value.compare_exchange_weak(cur_val, new_val,
63
28.9M
                                                                std::memory_order_relaxed)));
64
28.9M
        update_peak(new_val);
65
28.9M
        return true;
66
28.9M
    }
67
68
62.7M
    void sub(int64_t delta) { _current_value.fetch_sub(delta, std::memory_order_relaxed); }
69
70
488k
    void set(int64_t v) {
71
488k
        _current_value.store(v, std::memory_order_relaxed);
72
488k
        update_peak(v);
73
488k
    }
74
75
104M
    void update_peak(int64_t value) {
76
104M
        int64_t pre_value = _peak_value.load(std::memory_order_relaxed);
77
104M
        while (value > pre_value &&
78
104M
               !_peak_value.compare_exchange_weak(pre_value, value, std::memory_order_relaxed)) {
79
5.29k
        }
80
104M
    }
81
82
81.1M
    int64_t current_value() const { return _current_value.load(std::memory_order_relaxed); }
83
66.3M
    int64_t peak_value() const { return _peak_value.load(std::memory_order_relaxed); }
84
85
private:
86
    std::atomic<int64_t> _current_value {0};
87
    std::atomic<int64_t> _peak_value {0};
88
};
89
90
} // namespace doris