All Projects → OpenCloudOS → perf-monitor

OpenCloudOS / perf-monitor

Licence: other
Kernel profiler based on perf_event and ebpf

Programming Languages

c
50402 projects - #5 most used programming language
python
139335 projects - #7 most used programming language
Makefile
30231 projects
perl
6916 projects
awk
318 projects
Gherkin
971 projects

Projects that are alternatives of or similar to perf-monitor

perforator
Record "perf" performance metrics for individual functions/regions of an ELF binary.
Stars: ✭ 33 (+17.86%)
Mutual labels:  perf, profiling
terabit-network-stack-profiling
Tools for profiling the Linux network stack.
Stars: ✭ 68 (+142.86%)
Mutual labels:  perf, profiling
parca-agent
eBPF based always-on profiler auto-discovering targets in Kubernetes and systemd, zero code changes or restarts needed!
Stars: ✭ 250 (+792.86%)
Mutual labels:  profiling, ebpf
Flamegraph
Easy flamegraphs for Rust projects and everything else, without Perl or pipes <3
Stars: ✭ 2,185 (+7703.57%)
Mutual labels:  perf, profiling
audria
audria - A Utility for Detailed Ressource Inspection of Applications
Stars: ✭ 35 (+25%)
Mutual labels:  monitor, profiling
Mthawkeye
Profiling / Debugging assist tools for iOS. (Memory Leak, OOM, ANR, Hard Stalling, Network, OpenGL, Time Profile ...)
Stars: ✭ 1,119 (+3896.43%)
Mutual labels:  monitor, profiling
perf
Linux Perf subsystem bindings for Go
Stars: ✭ 19 (-32.14%)
Mutual labels:  perf, profiling
Hotspot
The Linux perf GUI for performance analysis.
Stars: ✭ 2,415 (+8525%)
Mutual labels:  perf, profiling
gl-bench
⏱ WebGL performance monitor with CPU/GPU load.
Stars: ✭ 146 (+421.43%)
Mutual labels:  monitor, profiling
Processhacker
A free, powerful, multi-purpose tool that helps you monitor system resources, debug software and detect malware.
Stars: ✭ 6,285 (+22346.43%)
Mutual labels:  monitor, profiling
Myperf4j
High performance Java APM. Powered by ASM. Try it. Test it. If you feel its better, use it.
Stars: ✭ 2,281 (+8046.43%)
Mutual labels:  monitor, profiling
Irpmon
The goal of the tool is to monitor requests received by selected device objects or kernel drivers. The tool is quite similar to IrpTracker but has several enhancements. It supports 64-bit versions of Windows (no inline hooks are used, only moodifications to driver object structures are performed) and monitors IRP, FastIo, AddDevice, DriverUnload and StartIo requests.
Stars: ✭ 248 (+785.71%)
Mutual labels:  monitor
Wam
Web App Monitor
Stars: ✭ 216 (+671.43%)
Mutual labels:  monitor
Webmonitor
实时监控网页变化,并发送通知(Monitor web page changes in real time and send notifications)
Stars: ✭ 212 (+657.14%)
Mutual labels:  monitor
Stonky
A command line dashboard for monitoring stocks
Stars: ✭ 208 (+642.86%)
Mutual labels:  monitor
celery-monitor
The celery monitor app was written by Django.
Stars: ✭ 92 (+228.57%)
Mutual labels:  monitor
Swmp
A responsive, eye-pleasing Linux server statistics dashboard.
Stars: ✭ 245 (+775%)
Mutual labels:  monitor
Uptime Monitor App
A PHP application to monitor uptime and ssl certificates
Stars: ✭ 205 (+632.14%)
Mutual labels:  monitor
Oknetworkmonitor
A network monitor for OkHttp.
Stars: ✭ 204 (+628.57%)
Mutual labels:  monitor
Adi
ADI(Android Debug Intensive) 是通过 JVMTI 实现的 Android 应用开发调试的增强工具集,目前主要提供性能相关的监控能力。
Stars: ✭ 194 (+592.86%)
Mutual labels:  monitor

基于perf的监控框架

基于libperflibtraceevent库实现简单的监控框架,提供比perf更灵活的特性。

  • 数据不落盘。
  • 数据过滤,基于tracepoint的过滤机制,减少数据量。
  • 数据实时处理并输出。不需要存盘后再处理。
  • 基于perf_event_open系统调用。

虽然比perf更灵活,但不能替代perf。perf灵活的符号处理,支持大量的event,支持很多硬件PMU特性。

perf-prof框架

1 框架介绍

内核态,采样事件经过filter过滤之后,存放到ringbuffer上,并递增counter计数器。只有经过filter过滤出来的事件才会放到ringbuffer。

  • 过滤器filter包含ebpf过滤器、pmu过滤器、ftrace过滤器(tracepoint),过滤可以减少事件量,筛选出感兴趣的事件。
  • 每个perf_event都有独立的ringbuffer,多个perf_event可以共用ringbuffer。ringbuffer上存放采样事件,包含一些基础数据,cpu、time、callchain等。采样默认关闭,通过perf_event_attr.sample_period参数开启采样。
  • 每个perf_event都有独立counter,不能共享。counter默认开启,不能关闭。计数和采样可以同时开启。

用户态,perf-prof框架不断读取ringbuffer的采样事件和counter,经过order排序事件,最后送到profiler处理事件。

  • order,按时间顺序排序事件,单个perf_event的ringbuffer上的事件是有序的,多个perf_event的ringbuffer不能保证顺序,需要排序合并起来。简化profiler的处理。order是可选项。

profiler,处理事件。决定打开哪些事件,如何处理事件。

  • profiler.init 初始化perf_event_attr打开对应的evsel,添加到evlist上,最终由libperf库调用perf_event_open系统调用打开perf_event。perf_event_attr.exclude_相关属性,用来配置pmu过滤器。
  • profiler.filter设置ebpf过滤器、ftrace过滤器。最终由libperf库通过ioctl设置到内核。
  • profiler.sample不断处理采样事件,完成分析工作。

2 Example: signal

一个最简单demo例子。

static profiler monitor_signal = {
    .name = "signal",
    .pages = 2,
    .init = signal_init,
    .filter = signal_filter,
    .deinit = signal_exit,
    .sample = signal_sample,
};
PROFILER_REGISTER(monitor_signal)

定义模块初始化、过滤、销毁、处理采样等接口。

3 profiler.init

static int signal_init(struct perf_evlist *evlist, struct env *env)
{
    struct perf_event_attr attr = {
        .type          = PERF_TYPE_TRACEPOINT,
        .config        = 0,
        .size          = sizeof(struct perf_event_attr),
        .sample_period = 1,
        .sample_type   = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_RAW |
                         (env->callchain ? PERF_SAMPLE_CALLCHAIN : 0),
        .read_format   = 0,
        .pinned        = 1,
        .disabled      = 1,
        .exclude_callchain_user = 1,
        .wakeup_events = 1, //1个事件
    };
    struct perf_evsel *evsel;
    int id;

    if (monitor_ctx_init(env) < 0)
        return -1;

    id = tep__event_id("signal", "signal_generate");
    if (id < 0)
        return -1;

    attr.config = id;
    evsel = perf_evsel__new(&attr);
    if (!evsel) {
        return -1;
    }
    perf_evlist__add(evlist, evsel);
    return 0;
}

定义perf_event_attr表示监控的事件。

tep__event_id("signal", "signal_generate"),获取signal:signal_generate tracepoint点的id。

perf_evsel__new(&attr),根据perf事件,创建evsel。1个evsel表示一个特点的事件,拿着这个事件可以到对应的cpu、线程上创建出perf_event。

perf_evlist__add(evlist, evsel),加到evlist。一个evlist表示一组evsel事件。

3.1 perf_event_attr

定义event的属性。可以指定perf命令定义的所有事件。

  • 硬件pmu事件
    • breakpoint事件
    • cpu事件
    • uncore事件
  • tracepoint点事件
  • kprobe事件
  • uprobe事件

可以通过ls /sys/bus/event_source/devices命令看到所有的事件类型。

  • perf_event_attr.type 事件类型

    PERF_TYPE_*
    	通过`cat /sys/bus/event_source/devices/*/type`获取类型。
    
  • perf_event_attr.config 事件配置

    根据不同的type, config值不一样。
    	PERF_TYPE_TRACEPOINT: config 指定tracepoint点的id.
    	PERF_TYPE_HARDWARE: config 指定特定的参数PERF_COUNT_HW_*
    
  • perf_event_attr.sample_period 采样周期

    定义采样周期, 发生多少次事件之后, 发起1个event到ring buffer
    
  • perf_event_attr.sample_type 采样类型

    PERF_SAMPLE_*
    	定义放到ring buffer的事件, 需要哪些字段
    
  • perf_event_attr.comm

    PERF_RECORD_COMM
    	记录进程comm和pid/tid的对应关系, 可以用于libtraceevent模块中tep_register_comm,
    	之后tep_print_event(ctx.tep, &s, &record, "%s", TEP_PRINT_COMM)就能打印出进程名
    	这样只能收集新创建进程的名字, 已启动进程的pid使用/proc/pid/comm来获取.
    
  • perf_event_attr.task

    PERF_RECORD_FORK/PERF_RECORD_EXIT
    	记录进程创建和退出事件
    
  • perf_event_attr.context_switch

    PERF_RECORD_SWITCH/PERF_RECORD_SWITCH_CPU_WIDE
    	记录进程切换信息
    

4 profiler.sample

static void signal_sample(union perf_event *event)
{
    // in linux/perf_event.h
    // PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_RAW
    struct sample_type_data {
        struct {
            __u32    pid;
            __u32    tid;
        }    tid_entry;
        __u64   time;
        struct {
            __u32    cpu;
            __u32    reserved;
        }    cpu_entry;
        struct {
            __u32   size;
	        __u8    data[0];
        } raw;
    } *data = (void *)event->sample.array;

    tep__update_comm(NULL, data->tid_entry.tid);
    print_time(stdout);
    tep__print_event(data->time/1000, data->cpu_entry.cpu, data->raw.data, data->raw.size);
}

根据perf_event_attr.sample_type来定义采样的事件的字段,可以还原出一个结构体。

tep__print_event,打印tracepoint事件。

5 基础功能

5.1 模块化

每个profiler都是独立的模块文件,可扩展,可裁减,损耗低。适合高性能监控场景。

5.2 栈

  • 栈及符号打印。可控制内核态、用户态、地址、符号、偏移量、dso、正向栈、反向栈,每个栈帧的分隔符、栈的分隔符。
  • 支持解析内核符号(/proc/kallsyms),用户态符号(.symtab/.dynsym)、MiniDebugInfo解析(.gnu_debugdata)。
  • 支持debuginfo包。/usr/lib/debug/.build-id/
  • key-value栈。以栈做为key,可以过滤重复栈,并能唯一寻址value。
  • 生成火焰图折叠栈格式。

5.3 用户态符号表

用户态符号表,使用syms_cache结构表示,通过pid找到特定于进程的syms符号集合。

syms符号集合由/proc/pid/maps内所有的文件映射组成,每一个文件映射由一个dso来表示,syms包含dso的集合。

每个dso由映射到进程地址空间内的[起始地址、结束地址、文件对象]表示。文件对象由object结构表示。

object结构表示一个动态库的符号集合,由多个sym组成。object是可以给多个进程共享的,通过引用计数管理object的引用和释放。

sym表示一个特定的符号。由符号名字,起始地址,大小组成。

syms_cache --> syms --> dso --> object --> sym

5.4 用户态内存泄露检测

LD_PRELOAD=/lib64/libtcmalloc.so HEAPCHECK=draconian PPROF_PATH=./perf-prof /path/to/bin

利用tcmalloc的内存泄露检测功能。

  • LD_PRELOAD=,预先加载tcmalloc库,替换glibc库的malloc和free函数。
  • HEAPCHECK=,内存泄露检测。draconian检测所有的内存泄露。
  • PPROF_PATH=,指定符号解析命令。perf-prof --symbols具备跟pprof --symbols一样的符号解析能力。

5.5 栈的处理

栈的处理方式各种各样,如perf top风格的栈负载处理,火焰图风格的栈处理。

perf-prof目前支持的栈处理。

  • 栈及符号打印。用callchain_ctx表示,定义了栈的打印风格,可控制内核态、用户态、地址、符号、偏移量、dso、正向栈、反向栈。每个栈帧的分隔符、栈的分隔符。
  • key-value栈。以栈做为key,可以过滤重复栈,并能唯一寻址value。用key_value_paires结构表示,一般相同的栈都有类似的作用,如内存分配栈,可以分析相同的栈分配的总内存量,未释放的总内存量。类似于gperftools提供的HEAPCHECKE功能,最后报告的内存泄露是以栈为基准的。
  • 火焰图。把相同的栈以及栈的每一帧聚合到一起。用flame_graph结构表示,能够生成折叠栈格式:反向栈、每帧以";"分隔、末尾是栈的数量。例子:swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 1。使用flamegraph.pl生成火焰图。

5.6 火焰图

perf-prof仅输出折叠栈格式,并对输出栈比较多的模块做了支持。目前已支持:profile, task-state, kmemleak, trace

原先在stdout直接输出栈,目前切换成火焰图之后,不会再输出栈,而是会在命令结束时输出火焰图折叠栈文件。通过[-g [--flame-graph file]]参数启用火焰图,必须支持栈(-g)才能输出火焰图。折叠栈文件以file.folded命名。使用flamegraph.pl最终生成svg火焰图。

$ perf-prof task-state -S --than 100 --filter cat -g --flame-graph cat
$ flamegraph.pl cat.folded > cat.svg

5.6.1 按时间的火焰图

是以固定间隔输出折叠栈,折叠栈包含时间戳。最终生成的火焰图是按时间排序的。对于长时间的监控,可以根据时间戳查找问题。

$ grep "15:46:33" cat.folded | flamegraph.pl > cat.svg #生成15:46:33秒开始的火焰图

5.6.2 网络丢包火焰图

$ perf-prof trace -e skb:kfree_skb -g --flame-graph kfree_skb -m 128 #监控丢包
$ perf-prof trace -e skb:kfree_skb -g --flame-graph kfree_skb -i 600000 -m 128 #每600秒间隔输出火焰图
$ flamegraph.pl --reverse  kfree_skb.folded > kfree_skb.svg #生成火焰图

5.6.3 CPU性能火焰图

$ perf-prof profile -F 1000 -C 0,1 --exclude-user -g --flame-graph profile #采样内核态CPU利用率的火焰图
$ perf-prof profile -F 1000 -C 0,1 --exclude-user -g --flame-graph profile -i 600000 #每600秒间隔输出火焰图
$ grep "15:46:33" profile.folded | flamegraph.pl > profile.svg #生成15:46:33秒开始600秒的火焰图

5.7 延迟处理

perf-prof目前支持的延迟处理。

  • 统计延迟。最大延迟,最小延迟,平均延迟。
  • 直方图。log2和linear直方图,使用print_log2_histprint_linear_hist函数打印。
  • 热图。横坐标是时间轴,纵坐标是延迟信息。目前支持:kvm-exit, multi-trace

5.8 热图

$ perf-prof multi-trace -e kvm:kvm_exit -e kvm:kvm_entry -C 1 --heatmap mpdelay
$ trace2heatmap.pl --unitstime=ns --unitslabel=ns --grid mpdelay-kvm_exit-kvm_entry.lat > mpdelay-kvm_exit-kvm_entry.svg

5.9 filter

目前支持3类过滤器:ebpf过滤器、pmu过滤器、ftrace过滤器。

通过perf-prof -h可以看到过滤器的选项:

Event selector. use 'perf list tracepoint' to list available tp events.
  EVENT,EVENT,...
  EVENT: sys:name[/filter/ATTR/ATTR/.../]
  filter: ftrace filter
  ATTR:
      ...
FILTER OPTION:
      --exclude-guest        exclude guest
      --exclude-kernel       exclude kernel
      --exclude-user         exclude user
      --exclude_pid=PID      ebpf, exclude pid
  -G, --exclude-host         Monitor GUEST, exclude host
      --irqs_disabled[=0|1]  ebpf, irqs disabled or not.
      --nr_running_max=N     ebpf, maximum number of running processes for CPU runqueue.
      --nr_running_min=N     ebpf, minimum number of running processes for CPU runqueue.
      --tif_need_resched[=0|1]   ebpf, TIF_NEED_RESCHED is set or not.

其中ebpf开头的是ebpf过滤器,其他的是pmu过滤器。ftrace过滤器,只能用于tracepoint事件。

5.9.1 ebpf过滤器

内核perf_event可以通过ioctl(PERF_EVENT_IOC_SET_BPF)来设置bpf程序。bpf程序返回1,可以继续采样;bpf程序返回0,终止采样。可以依据这样的策略,来给每个perf_event增加一个过滤器。过滤不需要的采样点。

当前支持4个ebpf过滤器。

  • --irqs_disabled,判断中断是否关闭。--irqs_disabled, --irqs_disabled=1中断关闭继续采样,中断打开终止采样。--irqs_disabled=0中断打开继续采样,中断关闭终止采样。
  • --tif_need_resched,判断TIF_NEED_RESCHED标记是否设置。--tif_need_resched, --tif_need_resched=1标记设置继续采样,标记未设置终止采样。--tif_need_resched=0标记未设置继续采样,标记设置终止采样。
  • --nr_running_min,--nr_running_max,判断runqueue中nr_running进程的数量。nr_running_min <= nr_running <= nr_running_max条件满足继续采样,否则终止采样。
  • --exclude_pid,过滤掉进程pid。当前进程等于PID终止采样,否则继续采样。

5.9.2 pmu过滤器

内核perf框架默认会带一些简单的过滤器,主要是基于perf_event_attr属性来设置。

当前支持4个pmu过滤器。

  • --exclude-guest,过滤掉guest模式。
  • --exclude-host,过滤掉host,只采样guest。一般用于硬件PMU。
  • --exclude-kernel,过滤掉内核态。
  • --exclude-user,过滤掉用户态。

5.9.3 ftrace过滤器

每个tracepoint事件都可以设置ftrace过滤器。

$ perf-prof trace -e 'sched:sched_stat_runtime help

perf-prof trace -e "sched:sched_stat_runtime/./[stack/]" [-g] [--flame-graph .] [-C .] [-p .] [-i .] [--order] [--order-mem .] [-m .] 

sched:sched_stat_runtime
name: sched_stat_runtime
ID: 237
format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3;       size:1; signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;

        field:char comm[16];    offset:8;       size:16;        signed:1;
        field:pid_t pid;        offset:24;      size:4; signed:1;
        field:u64 runtime;      offset:32;      size:8; signed:0;
        field:u64 vruntime;     offset:40;      size:8; signed:0;

print fmt: "comm=%s pid=%d runtime=%Lu [ns] vruntime=%Lu [ns]", REC->comm, REC->pid, (unsigned long long)REC->runtime, (unsigned long long)REC->vruntime

通过在命令末尾加上help可以查看详细的帮助信息,其中包含tracepoint点的格式,可以找到可以作为过滤器的参数。

perf-prof trace -e 'sched:sched_stat_runtime/runtime>1000000/'

过滤出runtime>1000000的数据,放到ringbuffer,再由profiler进一步处理。

5.10 Attach to

perf-prof 使用一些公共参数来控制perf_event附加到CPU、线程、cgroup上。

Usage: perf-prof [OPTION...] profiler [PROFILER OPTION...] [help] [cmd [args...]]
 OPTION:
      --cgroups=cgroup,...   Attach to cgroups, support regular expression.
  -C, --cpu=CPU[-CPU],...    Monitor the specified CPU, Dflt: all cpu
  -p, --pids=PID,...         Attach to processes
  -t, --tids=TID,...         Attach to threads

可以使用逗号分隔多个CPU、PID、TID、cgroup。

5.10.1 Attach to CPU

附加到CPU,只能监控指定的CPU上发生的事件。

perf-prof trace -e sched:sched_stat_runtime -C 0-1,3

5.10.2 Attach to PID/TID

附加到PID/TID,只能监控指定的线程上发生的事件。

perf-prof trace -e sched:sched_stat_runtime -p 205835,205982

perf-prof trace -e sched:sched_stat_runtime -t 205835,205982

附加到PID,会读取该pid下的所有线程,转换成附加到TID。

5.10.3 Attach to workload

附加到workload,监控workload执行过程中的事件。

会通过fork、execvp来执行workload,并得到workload的pid。转换成附加到PID。

perf-prof task-state ip link show eth0

可以使用--强制分隔perf-prof的参数和workload的参数。

5.10.4 Attach to cgroups

附加到cgroups,监控cgroup内所有进程发生的事件。如果附加的PID太多,可以把这些PID放到perf_event cgroup内,附加到该cgroup,就能够监控到所有这些进程的事件。

# Example 1:
mkdir /sys/fs/cgroup/perf_event/prof
echo 205835 > /sys/fs/cgroup/perf_event/prof/tasks
cat /proc/205835/cgroup | grep perf_event
  5:perf_event:/prof
perf-prof trace -e sched:sched_stat_runtime --cgroups 'prof' # prof
perf-prof trace -e sched:sched_stat_runtime --cgroups 'pro*' # 正则表达式

# Example 2:
mkdir /sys/fs/cgroup/perf_event/prof1
echo 205845 > /sys/fs/cgroup/perf_event/prof/tasks
perf-prof trace -e sched:sched_stat_runtime --cgroups 'prof,prof1'
perf-prof trace -e sched:sched_stat_runtime --cgroups 'prof*' # prof, prof1

perf_event cgroup 需要手动把需要观察的进程放进去。

cgroup的指定相对于/sys/fs/cgroup/perf_event/目录,同时可以使用正则表达式,匹配多个perf_event cgroup。

5.11 USDT

usdt是用户态进程静态导出的trace点,编译之后存放在.note.stapsdtsection中。解析该section,创建出uprobe就可以trace用户态执行。

目前提供3个功能:

  • list,列出elf文件中的usdt。
  • add,利用usdt添加uprobe点,通过profider:name方式来使用。
  • del,删除已添加的uprobe点。
# Example:
perf-prof usdt add libc:memory_malloc_retry@/usr/lib64/libc.so.6 -v
perf-prof trace -e libc:memory_malloc_retry

当前已支持x86和arm64平台。

Exploring USDT Probes on Linux

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].