| // 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/util/perf-counters.h |
| // and modified by Doris |
| |
| #pragma once |
| |
| #include <gen_cpp/Metrics_types.h> |
| #include <stdint.h> |
| |
| #include <iostream> |
| #include <string> |
| #include <vector> |
| |
| // This is a utility class that aggregates counters from the kernel. These counters |
| // come from different sources. |
| // - perf counter syscall (/usr/include/linux/perf_event.h") |
| // - /proc/self/io: io stats |
| // - /proc/self/status: memory stats |
| // The complexity here is that all these sources have data in a different and not |
| // easy to get at format. |
| // |
| // A typical usage pattern would be: |
| // PerfCounters counters; |
| // counters.add_default_counters(); |
| // counters.snapshot("After Init"); |
| // <do your work> |
| // counters.snapshot("After Work"); |
| // counters.PrettyPrint(cout); |
| // |
| // TODO: Expect PerfCounters to be refactored to ProcessState. |
| |
| namespace doris { |
| |
| class PerfCounters { |
| public: |
| enum Counter { |
| PERF_COUNTER_SW_CPU_CLOCK, |
| PERF_COUNTER_SW_PAGE_FAULTS, |
| PERF_COUNTER_SW_CONTEXT_SWITCHES, |
| PERF_COUNTER_SW_CPU_MIGRATIONS, |
| |
| PERF_COUNTER_HW_CPU_CYCLES, |
| PERF_COUNTER_HW_INSTRUCTIONS, |
| PERF_COUNTER_HW_CACHE_HIT, |
| PERF_COUNTER_HW_CACHE_MISSES, |
| PERF_COUNTER_HW_BRANCHES, |
| PERF_COUNTER_HW_BRANCH_MISSES, |
| PERF_COUNTER_HW_BUS_CYCLES, |
| |
| PERF_COUNTER_VM_USAGE, |
| PERF_COUNTER_VM_PEAK_USAGE, |
| PERF_COUNTER_RESIDENT_SET_SIZE, |
| |
| PERF_COUNTER_BYTES_READ, |
| PERF_COUNTER_BYTES_WRITE, |
| PERF_COUNTER_DISK_READ, |
| PERF_COUNTER_DISK_WRITE, |
| }; |
| |
| // Add the 'default' counters as ones to collect. Returns false if any of those |
| // counters are not available. |
| // Counters cannot be added after a snapshot has been taken. |
| bool add_default_counters(); |
| |
| // Add a specific counter to watch. Return false if that counter is not available. |
| // Counters cannot be added after a snapshot has been taken. |
| bool add_counter(Counter); |
| |
| // Take a snapshot of all the counters and store it. The caller can specify a name |
| // for the snapshot. |
| void snapshot(const std::string& name); |
| |
| // Returns the results of that snapshot |
| const std::vector<int64_t>* counters(int snapshot) const; |
| |
| // Returns readable names for the added counters |
| const std::vector<std::string>* counter_names() const { return &_counter_names; } |
| |
| // Prints out the names and results for all snapshots to 'out' |
| void pretty_print(std::ostream* out) const; |
| |
| PerfCounters(); |
| ~PerfCounters(); |
| |
| // Refactor |
| |
| struct ProcStatus { |
| int64_t vm_size = 0; |
| int64_t vm_peak = 0; |
| int64_t vm_rss = 0; |
| int64_t vm_hwm = 0; |
| }; |
| |
| static int parse_int(const std::string& state_key); |
| static int64_t parse_int64(const std::string& state_key); |
| static std::string parse_string(const std::string& state_key); |
| // Original data's unit is B or KB. |
| static int64_t parse_bytes(const std::string& state_key); |
| |
| // Flush cached process status info from `/proc/self/status`. |
| static void refresh_proc_status(); |
| static void get_proc_status(ProcStatus* out); |
| // Return the process actual physical memory in bytes. |
| static inline int64_t get_vm_rss() { return _vm_rss; } |
| static inline std::string get_vm_rss_str() { return _vm_rss_str; } |
| static inline int64_t get_vm_hwm() { return _vm_hwm; } |
| static inline int64_t get_vm_size() { return _vm_size; } |
| static inline int64_t get_vm_peak() { return _vm_peak; } |
| |
| private: |
| // Copy constructor and assignment not allowed |
| PerfCounters(const PerfCounters&); |
| PerfCounters& operator=(const PerfCounters&); |
| |
| bool init_sys_counter(Counter counter); |
| bool init_proc_self_io_counter(Counter counter); |
| bool init_proc_self_status_counter(Counter counter); |
| |
| bool get_sys_counters(std::vector<int64_t>& snapshot); |
| bool get_proc_self_io_counters(std::vector<int64_t>& snapshot); |
| bool get_proc_self_status_counters(std::vector<int64_t>& snapshot); |
| |
| enum DataSource { |
| SYS_PERF_COUNTER, |
| PROC_SELF_IO, |
| PROC_SELF_STATUS, |
| }; |
| |
| struct CounterData { |
| Counter counter; |
| DataSource source; |
| TUnit::type type; |
| |
| // DataSource specific data. This is used to pull the counter values. |
| union { |
| // For SYS_PERF_COUNTER. File descriptor where the counter value is stored. |
| int64_t fd; |
| // For PROC_SELF_IO. Line number from /proc/self/io file with this counter's value |
| int proc_io_line_number; |
| }; |
| // For PROC_SELF_STATUS. Field name for counter |
| std::string proc_status_field; |
| }; |
| |
| std::vector<CounterData> _counters; |
| std::vector<std::string> _counter_names; |
| std::vector<std::string> _snapshot_names; |
| std::vector<std::vector<int64_t>> _snapshots; |
| // System perf counters can be grouped together. The OS will update all grouped counters |
| // at the same time. This is useful to better correlate counter values. |
| int64_t _group_fd; |
| |
| static int64_t _vm_rss; |
| static std::string _vm_rss_str; |
| static int64_t _vm_hwm; |
| static int64_t _vm_size; |
| static int64_t _vm_peak; |
| }; |
| |
| } // namespace doris |