首页 > 编程语言 >基于eBPF的procstat软件追踪程序Offcpu时间

基于eBPF的procstat软件追踪程序Offcpu时间

时间:2024-07-12 18:55:25浏览次数:14  
标签:offcpu eBPF 程序 procstat 进程 软件 Offcpu

在现代计算机系统中,性能调优和问题诊断是大家经常会面临的问题,解决这些性能问题是确保程序高效运行的关键。有时不知为何程序的吞吐量和时延出现抖动,有一种可能就是程序发生了Offcpu。了解程序的 Offcpu 时间有助于识别潜在的性能瓶颈和系统资源调度问题。今天,我们将介绍一款强大的性能追踪软件——procstat,它使用 eBPF 技术来追踪程序的Offcpu时间,并通过一个小例子展示它的使用方法。
之前写过关于procstat软件的文章,使用procstat软件检测死锁问题使用procstat软件追踪加锁和持有锁的时间,欢迎大家阅读。

什么是 Offcpu

Offcpu 时间指的是一个线程在非运行状态下所花费的时间。这可能是由于被其他线程抢占、等待 I/O 操作完成或其他原因。有很多时候,程序发生的性能抖动是由于Offcpu导致。通过分析程序的Offcpu 情况,我们可以更好地理解线程调度和系统资源的使用情况,从而进行性能优化。

procstat软件简介

procstat是一款基于eBPF的监控工具软件,运行在Linux平台,主要用于跟踪目标程序的运行状态,并报告异常指标,是分析程序性能问题的一大利器。procstat能够用于追踪程序的Offcpu时间。该软件通过eBPF技术,可以深入到Linux内核内部,监控操作系统的调度行为,实时捕捉程序的调度状态。当检测到Offcpu时间超过阈值的情况时,procstat会在日志中输出详细的信息,帮助开发者快速定位问题根源。接下来我们将通过一个小实验来展示一下procstat软件是如何追踪程序Offcpu时间的。
此软件可以在以下链接中下载到,并提供免费试用,后续还会有版本更新迭代,使用时需要能连互联网环境。
Github下载链接

Offcpu示例代码

我们通过一个简单的 C++ 程序来演示如何使用 procstat 追踪Offcpu时间。以下是我们的示例程序:

#include <iostream>
#include <thread>
#include <chrono>
int main()
{
    while (1) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return 0;
}
// g++ offcpu.cpp -o offcpu -g -std=c++11 -pthread -O2

这个程序简单地在一个无限循环中每次休眠 1 毫秒,然后继续运行。程序的休眠在实际应用中可能代表等待 I/O 或者其他资源的情况。

使用procstat追踪Offcpu

编译并启动上述代码后,使用procstat软件来监控该程序并检测Offcpu状态。本实验中,编译后的程序名为offcpu。首先,将procstat软件的配置中将offcpu的阈值设置为900000,单位是纳秒,意思是当进程发生Offcpu时长超过阈值900微秒就会输出日志。
配置设置
配置文件位置在procstat目前下的conf目录中,名为config.json。

"schedule_stat": {
        "offcpu_duration": 900000
},

我们可以通过以下命令启动procstat进行监控:sh start.sh -p 进程号。其中,<进程号>是正在运行的offcpu程序的进程ID。
运行程序

[root@VM-8-2-centos bin]# ps -ef | grep offcpu
root     2896306 2894954  0 14:38 pts/2    00:00:12 ./offcpu
root     2911886 2911344  0 15:29 pts/4    00:00:00 grep --color=auto offcpu
[root@VM-8-2-centos bin]# sh start.sh -p 2896306
Start Loading...!
Start Stating...!

启动监控后(输出“Start Stating…!”后就已开始监控了),procstat会持续监控该程序的运行状态,并在日志中记录时间超过配置文件中设定的阈值的Offcpu操作(时长可配置)。

procstat软件日志

接下来我们查询procstat的日志信息,并搜索SCHED OFFCPU关键字。
offcpu日志图在日志中发现offcpu进程非常频繁地进入Offcpu状态,从结果图中也可看出,被监控的offcpu进程的确进入过Offcpu状态,我们截取几条日志分析一下。

  1. 第13667行,是表示该进程发生Offcpu的时长超过了阈值,各字段含义:
    (1)comm=offcpu,表示发生Offcpu的进程的启动命令是offcpu;
    (2)tid=2896306,表示发生Offcpu的线程id是2896306;
    (3)state=1,表示Offpu的类型,1是可打断的,2是不可打断的;
    (4)duration=[1068527]ns,表示本次Offcpu的时长是1068527纳秒,约为1ms;
    (5)preempt_pid=0,表示抢占该进程的抢占者进程id是0;
    (6)preempt_tid=0,表示抢占该进程的抢占者线程id是0;
    (7)preempt_comm=swapper/0,表示抢占该进程的抢占者进程命令是swapper/0;
    (8)waker_pid=0,表示唤醒该进程的唤醒者进程id是0;
    (9)waker_tid=0,表示唤醒该进程的唤醒者线程id是0;
    (10)waker_comm=swapper/0,表示唤醒该进程的唤醒者进程命令是swapper/0。
  2. 第13668行是发生Offput时的线程堆栈信息,可以看到是由于用户空间调用了sleep导致进程被调度出运行队列导致的Offcpu。
  3. 第13683行是唤醒offcpu进程的线程的堆栈信息,可以看到是定时器发生了中断,之后唤醒了offcpu进程,也就是sleep的时间到了被唤醒了。
  4. 第13701行是50ms输出一次的Offcpu状态的统计信息,其包含的字段意义如下:
    (1)tid = 2896306,表示发生Offcpu的线程id;
    (2)pid = 2896306,表示发生Offcpu的进程id;
    (3)comm = offcpu,表示发生Offcpu的进程的启动命令是offcpu;
    (4)total_duration = 25574161ns,表示该统计周期内此进程发生Offcpu的总时长是25ms;
    (5)avg_duration = 1065590ns,表示该统计周期内此进程发生Offcpu的平均时长是1ms;
    (6)max_duration = 1071927ns,表示该统计周期内此进程发生Offcpu的最大时长是1ms;
    (7)max_index = 18,表示该统计周期内时长最大的Offcpu发生在第18次;
    (8)count = 24,表示该统计周期内一共发生了24次Offcpu。

通过分析这些信息就能知道发生Offcpu的真正原因,在分析程序的性能抖动时非常有帮助!

总结

procstat 是一个功能强大的工具,通过 eBPF 技术实现了对程序 Offcpu 时间的全面追踪。通过本文的介绍和示例,相信你已经对 procstat 有了基本的了解。希望你能在实际工作中充分利用这个软件,提高程序的性能和稳定性。
procstat软件还可以监测很多的程序异常状态,随着eBPF技术的不断发展和procstat软件不断的迭代,希望能够帮助大家定位程序的性能问题和异常问题,进一步提升对软件和操作系统的监控能力,欢迎大家试用,有问题请私信我,共同学习、交流,共同进步!

标签:offcpu,eBPF,程序,procstat,进程,软件,Offcpu
From: https://blog.csdn.net/2401_84703565/article/details/140380159

相关文章

  • eBPF 容器持久化map到宿主机上
    问题现象k8s上启动pod后,使用主机网络的容器,加载eBPF程序到网口上,持久化map只能保存在容器文件系统/sys/fs/bpf中。容器复位后,新容器与原来eBPF程序使用的不是同一个map。问题分析新容器使用新的文件系统,无法找回原来的/sys/fs/bpf挂载点,需要持久化到宿主机上。k8s挂载传播,实现......
  • eBPF 用户态和内核态基于ringbuf交互
    相比于perf_event_array,ringbuf优势在于1.读取数据是有序的,即提交顺序和消费顺序保持一致。2.避免数据复制,即提交数据到map和传递到用户态都不需要拷贝。内核态ringbuf/ringbuf.c#include"../headers/vmlinux.h"#include"../headers/bpf_endian.h"#include"../headers/b......
  • 基于eBPF的procstat软件追踪等待锁和持有锁的时间
    在并发编程中,锁的使用是保证线程安全的重要手段。然而,过度使用锁或者锁竞争可能导致性能瓶颈。为了分析程序中锁的使用情况,我们可以借助procstat软件来追踪程序加锁时间和等待锁的时间。procstat是一个基于eBPF(extendedBerkeleyPacketFilter)的软件,能够对系统的各种行为进......
  • 香橙派编译linux内核支持ebpf和虚拟WIFI
    前言上一篇文章香橙派5plus上跑云手机方案一redroid(带硬件加速)中说了怎么运行redroid,这篇补一下怎么修改参数编译内核。补充上篇文章有个内容需要补充一下:更新完内核需要用下面的命令防止内核被apt更新,不然后面使用aptupdate又回到官方的内核(注意版本号,当前是1009)。sudo......
  • eBPF常用map类型
    map种类map类型特点HashMapBPF_MAP_TYPE_HASHhashmap。BPF_MAP_TYPE_PERCPU_HASHpercore的hashmap。BPF_MAP_TYPE_LRU_HASHmap塞满之后,继续插入,自动删除最近最少使用的entry。ArrayMapBPF_MAP_TYPE_ARRAY数组,key是整数。......
  • eBPF约束
    内核态约束1.内核态eBPF无法使用C语言标准库。因为不支持malloc,所以无法扩展skb空间且无法直接从内核态拷贝整个报文到用户态。2.内核态eBPF无法获取当前时间,bpf_ktime_get_ns函数返回系统启动后运行纳秒数,不包括系统暂停时间。https://www.man7.org/linux/man-pages/man7/bpf......
  • eBPF基于LPM实现路由匹配
    基于eBPFlpmmap,icmp只有匹配上路由才能通。最终目录结构效果展示启动应用前,可以ping通192.168.0.1和192.168.0.105。启动应用后,无法ping通192.168.0.1,可以ping通192.168.0.105。停止应用后,可以ping通192.168.0.1和192.168.0.105。icmp/drop-icmp.c#include"../heade......
  • ebpf在Android安全上的应用:ebpf的一些基础知识(上篇)
    ebpf在Android安全上的应用:ebpf的一些基础知识(上篇)一、ebpf介绍eBPF是一项革命性的技术,起源于Linux内核,它可以在特权上下文中(如操作系统内核)运行沙盒程序。它用于安全有效地扩展内核的功能,而无需通过更改内核源代码或加载内核模块的方式来实现。(PS:介绍来源于https://ebpf.i......
  • 操作系统是否支持ebpf特性检查
    内核版本信息uname-a操作系统信息cat/etc/os-release查看是否支持kprobe事件zcat/proc/config.gz|grepCONFIG_KPROBE_EVENTSorcat/boot/config-$(uname-r)|grepCONFIG_KPROBE_EVENTS查看是否配置为CONFIG_KPROBE_EVENTS=y查看是否支持uprobe事件zcat/proc/......
  • eBPF xdp和tc区别
     xdptc层次网卡驱动层数据链路层位置进入Linux网络协议栈之前在Linux网络协议栈中方向只有ingress有ingress和egress修改支持修改报文支持修改报文,有skb结构,修改更方便cilium加载eBPF到虚拟网卡tc上来实现流量转发。......