Ubuntu,如何找到内核工作繁重的程序热点?似乎kernel.kallsyms上的函数没有标记为用户空间函数的子级

Ubuntu, how to find hotspot of program with heavy kernel work? It seems function at kernel.kallsyms doesn't mark as user space function's children

本文关键字:函数 kallsyms 空间 用户 记为 kernel 内核 何找 工作 Ubuntu 热点      更新时间:2023-10-16

具有繁重内核工作(锁定解锁)的多线程程序,尝试使用评测工具在我的代码中找到热点。

我写了一个最低限度的可复制程序。编译它。使用诸如perf、gprof之类的分析工具和调用堆栈记录。然后没有人可以报告我代码中的热点,但可以报告内核或libstdc++.so.中的函数

#include <iostream>
#include <mutex>
#include <thread>
#include <memory>
#include <vector>
std::mutex mtx;
long long_val = 0;
void do_something(long &val)
{
std::unique_lock<std::mutex> lck(mtx);
for(int j=0; j<1000; ++j)
val++;
}

void thread_func()
{
for(int i=0; i<1000000L; ++i)
{
do_something(long_val);
}
}

int main(int argc, char* argv[])
{
std::vector<std::unique_ptr<std::thread>> threads;
for(int i=0; i<100; ++i)
{
threads.push_back(std::move(std::unique_ptr<std::thread>(new std::thread(thread_func))));
}
for(int i=0; i<100; ++i)
{
threads[i]->join();
}
threads.clear();
std::cout << long_val << std::endl;
return 0;
}

正如我们所看到的,do_something()是我的节目的热点。由于过多的unique_lock占用了大量的内核工作,并且1000次inc操作该函数。

我想让评测工具告诉我,它是do_something()做了很多锁,导致了很多内核工作。但从perf,我只能发现它是锁减慢了我的代码,但这些锁是在哪里对我的代码进行操作的?目前还不清楚

编译:

g++ -o a.out -O3 -std=c++11 -fno-omit-frame-pointer -pthread -pg main.cpp

运行程序./a.out,htop报告内核占用了一半的CPU资源。

Perf记录:

perf record -g ./a.out

Perf报告:

Children      Self  Command  Shared Object        Symbol
-   98.64%     0.00%  a.out    libstdc++.so.6.0.21  [.] 0x00000000000b8c80
- 0xb8c80
+ 41.80% __lll_unlock_wake
+ 35.39% __lll_lock_wait
12.77% pthread_mutex_lock
7.69% pthread_mutex_unlock
0.70% _Z11thread_funcv
-   49.21%     0.88%  a.out    [kernel.kallsyms]    [k] entry_SYSCALL_64_after_hwframe
+ 48.33% entry_SYSCALL_64_after_hwframe
0.88% 0xb8c80
-   47.64%     1.06%  a.out    [kernel.kallsyms]    [k] do_syscall_64
+ 46.59% do_syscall_64
+ 1.06% 0xb8c80
-   47.18%     1.44%  a.out    [kernel.kallsyms]    [k] sys_futex
+ 45.74% sys_futex
+ 1.44% 0xb8c80
-   45.55%     1.65%  a.out    [kernel.kallsyms]    [k] do_futex
+ 43.90% do_futex
+ 1.65% 0xb8c80
-   41.80%     1.30%  a.out    libpthread-2.23.so   [.] __lll_unlock_wake
+ 40.50% __lll_unlock_wake
+ 1.30% 0xb8c80
-   35.39%     4.53%  a.out    libpthread-2.23.so   [.] __lll_lock_wait
+ 30.86% __lll_lock_wait
+ 4.53% 0xb8c80
-   20.51%     5.40%  a.out    [kernel.kallsyms]    [k] futex_wake
+ 15.11% futex_wake
+ 5.40% 0xb8c80
-   19.41%     0.88%  a.out    [kernel.kallsyms]    [k] futex_wait
+ 18.53% futex_wait
+ 0.88% 0xb8c80
-   16.92%     6.25%  a.out    [kernel.kallsyms]    [k] _raw_spin_lock
+ 10.67% _raw_spin_lock
+ 6.25% 0xb8c80
-   12.77%    12.73%  a.out    libpthread-2.23.so   [.] pthread_mutex_lock
12.73% 0xb8c80
pthread_mutex_lock
+   11.80%     5.41%  a.out    [kernel.kallsyms]    [k] futex_wait_setup
+   11.05%    11.05%  a.out    [kernel.kallsyms]    [k] syscall_return_via_sysret
+   10.68%    10.67%  a.out    [kernel.kallsyms]    [k] native_queued_spin_lock_slowpath
+    7.69%     7.65%  a.out    libpthread-2.23.so   [.] pthread_mutex_unlock
+    7.36%     0.11%  a.out    [kernel.kallsyms]    [k] wake_up_q
+    7.17%     1.27%  a.out    [kernel.kallsyms]    [k] try_to_wake_up
+    4.42%     0.23%  a.out    [kernel.kallsyms]    [k] futex_wait_queue_me
+    4.17%     0.08%  a.out    [kernel.kallsyms]    [k] schedule
+    3.84%     0.75%  a.out    [kernel.kallsyms]    [k] __schedule
+    2.70%     0.01%  a.out    [kernel.kallsyms]    [k] ttwu_do_activate
+    2.49%     2.48%  a.out    [kernel.kallsyms]    [k] get_futex_value_locked
+    2.38%     0.11%  a.out    [kernel.kallsyms]    [k] activate_task
+    2.26%     0.15%  a.out    [kernel.kallsyms]    [k] enqueue_task_fair
+    1.88%     1.88%  a.out    [unknown]            [k] 0xfffffe000000601b
+    1.84%     0.15%  a.out    [kernel.kallsyms]    [k] __task_rq_lock
+    1.78%     1.78%  a.out    [unknown]            [k] 0xfffffe000005e01b
+    1.77%     1.77%  a.out    [unknown]            [k] 0xfffffe000003201b
+    1.67%     0.02%  a.out    [kernel.kallsyms]    [k] deactivate_task
+    1.66%     1.66%  a.out    [unknown]            [k] 0xfffffe000008a01b  

我如何使用评测工具,在我真正的程序中找出这种类型的热点。我不想每次都用"二进制chop注释"来解决它。谢谢

perf默认使用帧指针展开,这很快,但不可靠。即使您的应用程序没有省略帧指针,库也可能

或者,您可以将--call-graphdwarflbr一起使用。

dwarf在采样期间记录稍后评估的堆栈块。它可以提供更多的细节,但会产生巨大的痕迹,可能会有更多的扰动。

lbr需要在较新的英特尔处理器上提供硬件支持。

它会显示这样的内容:

99.25%     2.61%  a.out    a.out                [.] thread_func
|          
|--97.67%--thread_func
|          |          
|          |--45.33%--pthread_mutex_lock@plt
|          |          
|          |--28.65%--pthread_mutex_unlock@plt
|          |          
|          |--18.88%--__pthread_mutex_lock
|          |          __lll_lock_wait
|          |          
|           --4.75%--__pthread_mutex_unlock_usercnt
|                     __lll_unlock_wake
|          
--0.72%--__pthread_mutex_lock