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

时间:2019-01-21 12:53:44

标签: c++ profiling perf gprof

具有繁重的内核工作(锁定解锁)的多线程程序,请尝试使用性能分析工具在我的代码中查找热点。

我写了一个最小的可复制程序。编译它。将性能分析工具(如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会花费大量内核工作,并且该函数的inc运算量为1000倍。

我想使用分析工具告诉我,do_something()会产生很多锁定,导致大量内核工作。但是从perf,我只能发现它是锁使我的代码变慢,但是使这些锁在我的代码上运行的地方呢?还不清楚。

编译:

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

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

性能记录:

perf record -g ./a.out

性能报告:

      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  

如何在我的程序中使用概要分析工具找出此类热点。我不想每次都使用“二进制印章注释”来解决它。谢谢!

1 个答案:

答案 0 :(得分:1)

perf默认情况下使用框架指针展开,这是快速的,但是并不可靠。即使您的应用程序不省略帧指针,库也可能会如此。

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

dwarf记录采样期间的堆栈块,这些块稍后进行评估。它可以提供更多细节,但会留下大量痕迹,并且可能会带来更多干扰。

lbr需要较新的Intel处理器提供硬件支持。

它将显示如下内容:

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