169 lines
5.6 KiB
C++
169 lines
5.6 KiB
C++
// 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 <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "util/debug_util.h"
|
|
|
|
// 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;
|
|
};
|
|
|
|
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; }
|
|
|
|
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.
|
|
int 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.
|
|
int _group_fd;
|
|
|
|
static int64_t _vm_rss;
|
|
static std::string _vm_rss_str;
|
|
};
|
|
|
|
} // namespace doris
|