Coverage Report

Created: 2024-11-21 14:46

/root/doris/be/src/util/perf_counters.h
Line
Count
Source (jump to first uncovered line)
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
// https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/perf-counters.h
19
// and modified by Doris
20
21
#pragma once
22
23
#include <gen_cpp/Metrics_types.h>
24
#include <stdint.h>
25
26
#include <iostream>
27
#include <string>
28
#include <vector>
29
30
// This is a utility class that aggregates counters from the kernel.  These counters
31
// come from different sources.
32
//   - perf counter syscall (/usr/include/linux/perf_event.h")
33
//   - /proc/self/io: io stats
34
//   - /proc/self/status: memory stats
35
// The complexity here is that all these sources have data in a different and not
36
// easy to get at format.
37
//
38
// A typical usage pattern would be:
39
//  PerfCounters counters;
40
//  counters.add_default_counters();
41
//  counters.snapshot("After Init");
42
//  <do your work>
43
//  counters.snapshot("After Work");
44
//  counters.PrettyPrint(cout);
45
//
46
// TODO: Expect PerfCounters to be refactored to ProcessState.
47
48
namespace doris {
49
50
class PerfCounters {
51
public:
52
    enum Counter {
53
        PERF_COUNTER_SW_CPU_CLOCK,
54
        PERF_COUNTER_SW_PAGE_FAULTS,
55
        PERF_COUNTER_SW_CONTEXT_SWITCHES,
56
        PERF_COUNTER_SW_CPU_MIGRATIONS,
57
58
        PERF_COUNTER_HW_CPU_CYCLES,
59
        PERF_COUNTER_HW_INSTRUCTIONS,
60
        PERF_COUNTER_HW_CACHE_HIT,
61
        PERF_COUNTER_HW_CACHE_MISSES,
62
        PERF_COUNTER_HW_BRANCHES,
63
        PERF_COUNTER_HW_BRANCH_MISSES,
64
        PERF_COUNTER_HW_BUS_CYCLES,
65
66
        PERF_COUNTER_VM_USAGE,
67
        PERF_COUNTER_VM_PEAK_USAGE,
68
        PERF_COUNTER_RESIDENT_SET_SIZE,
69
70
        PERF_COUNTER_BYTES_READ,
71
        PERF_COUNTER_BYTES_WRITE,
72
        PERF_COUNTER_DISK_READ,
73
        PERF_COUNTER_DISK_WRITE,
74
    };
75
76
    // Add the 'default' counters as ones to collect.  Returns false if any of those
77
    // counters are not available.
78
    // Counters cannot be added after a snapshot has been taken.
79
    bool add_default_counters();
80
81
    // Add a specific counter to watch.  Return false if that counter is not available.
82
    // Counters cannot be added after a snapshot has been taken.
83
    bool add_counter(Counter);
84
85
    // Take a snapshot of all the counters and store it.  The caller can specify a name
86
    // for the snapshot.
87
    void snapshot(const std::string& name);
88
89
    // Returns the results of that snapshot
90
    const std::vector<int64_t>* counters(int snapshot) const;
91
92
    // Returns readable names for the added counters
93
0
    const std::vector<std::string>* counter_names() const { return &_counter_names; }
94
95
    // Prints out the names and results for all snapshots to 'out'
96
    void pretty_print(std::ostream* out) const;
97
98
    PerfCounters();
99
    ~PerfCounters();
100
101
    // Refactor
102
103
    struct ProcStatus {
104
        int64_t vm_size = 0;
105
        int64_t vm_peak = 0;
106
        int64_t vm_rss = 0;
107
        int64_t vm_hwm = 0;
108
    };
109
110
    static int parse_int(const std::string& state_key);
111
    static int64_t parse_int64(const std::string& state_key);
112
    static std::string parse_string(const std::string& state_key);
113
    // Original data's unit is B or KB.
114
    static int64_t parse_bytes(const std::string& state_key);
115
116
    // Flush cached process status info from `/proc/self/status`.
117
    static void refresh_proc_status();
118
    static void get_proc_status(ProcStatus* out);
119
    // Return the process actual physical memory in bytes.
120
1.79k
    static inline int64_t get_vm_rss() { return _vm_rss; }
121
0
    static inline std::string get_vm_rss_str() { return _vm_rss_str; }
122
0
    static inline int64_t get_vm_hwm() { return _vm_hwm; }
123
0
    static inline int64_t get_vm_size() { return _vm_size; }
124
0
    static inline int64_t get_vm_peak() { return _vm_peak; }
125
126
private:
127
    // Copy constructor and assignment not allowed
128
    PerfCounters(const PerfCounters&);
129
    PerfCounters& operator=(const PerfCounters&);
130
131
    bool init_sys_counter(Counter counter);
132
    bool init_proc_self_io_counter(Counter counter);
133
    bool init_proc_self_status_counter(Counter counter);
134
135
    bool get_sys_counters(std::vector<int64_t>& snapshot);
136
    bool get_proc_self_io_counters(std::vector<int64_t>& snapshot);
137
    bool get_proc_self_status_counters(std::vector<int64_t>& snapshot);
138
139
    enum DataSource {
140
        SYS_PERF_COUNTER,
141
        PROC_SELF_IO,
142
        PROC_SELF_STATUS,
143
    };
144
145
    struct CounterData {
146
        Counter counter;
147
        DataSource source;
148
        TUnit::type type;
149
150
        // DataSource specific data.  This is used to pull the counter values.
151
        union {
152
            // For SYS_PERF_COUNTER. File descriptor where the counter value is stored.
153
            int fd;
154
            // For PROC_SELF_IO.  Line number from /proc/self/io file with this counter's value
155
            int proc_io_line_number;
156
        };
157
        // For PROC_SELF_STATUS.  Field name for counter
158
        std::string proc_status_field;
159
    };
160
161
    std::vector<CounterData> _counters;
162
    std::vector<std::string> _counter_names;
163
    std::vector<std::string> _snapshot_names;
164
    std::vector<std::vector<int64_t>> _snapshots;
165
    // System perf counters can be grouped together.  The OS will update all grouped counters
166
    // at the same time.  This is useful to better correlate counter values.
167
    int _group_fd;
168
169
    static int64_t _vm_rss;
170
    static std::string _vm_rss_str;
171
    static int64_t _vm_hwm;
172
    static int64_t _vm_size;
173
    static int64_t _vm_peak;
174
};
175
176
} // namespace doris