在并发编程中,锁的使用是保证线程安全的重要手段。然而,过度使用锁或者锁竞争可能导致性能瓶颈。为了分析程序中锁的使用情况,我们可以借助procstat软件来追踪程序加锁时间和等待锁的时间。procstat是一个基于eBPF(extended Berkeley Packet Filter)的软件,能够对系统的各种行为进行细粒度的追踪和分析。
之前写过一篇的使用procstat软件检测死锁问题文章,欢迎大家阅读。
procstat软件简介
procstat是一款基于eBPF的监控工具软件,运行在Linux平台,主要用于跟踪目标程序的运行状态,并报告异常指标,是分析程序性能问题的一大利器。同时,procstat也可用于追踪C/C++程序的等待锁和持有锁的时间。该软件通过eBPF技术,可以深入到标准库内部,监控线程的锁定和解锁行为,实时捕捉程序的运行状态。当检测到加锁和等待锁时间超过阈值的情况时,procstat会在日志中输出详细的警告信息,帮助开发者快速定位问题根源。接下来我们将通过一个小实验来展示一下procstat软件是如何追踪程序等待锁和持有锁的时间的。
此软件可以在以下链接中下载到,并提供免费试用,后续还会有版本更新迭代,使用时需要能连互联网环境。
Github下载链接
多线程加锁示例代码
本文将使用以下示例程序,演示如何使用procstat软件来分析锁的使用情况。
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void func1()
{
while (1) {
std::lock_guard<std::mutex> lock(mtx);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void func2()
{
while (1) {
std::lock_guard<std::mutex> lock(mtx);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void func3()
{
while (1) {
bool is_lock = mtx.try_lock();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (is_lock) {
mtx.unlock();
}
}
}
int main()
{
std::thread t1(&func1);
std::thread t2(&func2);
std::thread t3(&func3);
t1.join();
t2.join();
return 0;
}
在以上代码中,创建了3个子线程func1、func2、func3和1个互斥锁mtx,这三个线程都尝试争抢这个锁,持有成功后sleep 1毫秒,然后将锁释放。
使用procstat追踪锁操作
编译并启动上述代码后,使用procstat软件来监控该程序并检测锁操作。本实验中,编译后的程序名为test。首先,将procstat软件的配置中将持有锁和等待锁的阈值设置为0,单位是纳秒,意思是当进程持有锁时长和等待锁时长超过阈值就会输出警告日志。
配置设置
配置文件位置在procstat目前下的conf目录中,名为config.json。
"lock_stat": {
"lock_duration": 0,
"wait_lock_duration": 0
}
我们可以通过以下命令启动procstat进行监控:sh start.sh -p 进程号。其中,<进程号>是正在运行的test程序的进程ID。
运行程序
[root@VM-8-2-centos bin]# ./test &
[1] 1543495
[root@VM-8-2-centos bin]#
[root@VM-8-2-centos bin]# sh start.sh -p 1543495
Start Loading...!
Start Stating...!
启动监控后(输出“Start Stating…!”后就已开始监控了),procstat会持续监控该程序的运行状态,并在日志中记录时间超过配置文件中设定的阈值的锁定和解锁操作(时长可配置)。
procstat软件日志
接下来我们查询procstat的日志信息,并搜索LOCK、WAIT LOCK关键字。
从结果图中可看出,被监控的test进程的不同线程都在进行抢锁的操作,并且持有锁的时长([LOCK]关键字)都是1ms左右,等待锁的时长([WAIT LOCK]关键字)也被统计出来。
总结
锁操作是多线程编程中常用的技术。基于eBPF的procstat软件通过实时监控程序的锁操作,提供了一种高效且精确的追踪加锁和等待锁时长的功能。通过深入标准库内部的监控,procstat能够帮助开发者快速定位锁性能问题,提升程序的稳定性和可靠性。
procstat软件还可以监测很多的程序异常状态,随着eBPF技术的不断发展和procstat软件不断的迭代,希望能够帮助大家定位程序的性能问题和异常问题,进一步提升对软件和操作系统的监控能力,欢迎大家试用,有问题请私信我,共同学习、交流,共同进步!