gperftools如何获取每个线程的cpu分析?

问题描述 投票:0回答:1

我已经阅读了gperftools的源代码(https://github.com/gperftools/gperftools/blob/f7c6fb6c8e99d6b1b725e5994373bcd19ffdf8fd/src/profile-handler.cc#:~:text=sevp.sigev_notify_thread_id%20%3D%20systidcall(SYS_getsyscall )%3B).

static void StartLinuxThreadTimer(int timer_type, int signal_number,
                                  int32 frequency, pthread_key_t timer_key) {
  int rv;
  struct sigevent sevp;
  timer_t timerid;
  struct itimerspec its;
  memset(&sevp, 0, sizeof(sevp));
  sevp.sigev_notify = SIGEV_THREAD_ID;
  **sevp.sigev_notify_thread_id = syscall(SYS_gettid);**
  sevp.sigev_signo = signal_number;
  clockid_t clock = CLOCK_THREAD_CPUTIME_ID;
  // other code
}

上面的代码表明SIGPROF只会被调用ProfilerStart函数的当前线程处理。那么 gperftools 是如何获取其他线程的 cpu profiling 的呢?

我已经阅读了源代码并用谷歌搜索了我的问题。

c++ linux profiling gperftools
1个回答
0
投票

请注意,此代码仅在设置了 per_thread_timer_enabled_ 时使用。默认情况下未设置。启用此模式后,用户应从每个线程调用 ProfileHandlerRegisterThread。在 https://github.com/alk/gperf-all-threads 有一个“自动”执行此操作的助手,但我仍然不确定是否能够依赖这个东西(关于符号插入和各种细节的很多细节链接模式)。

在“stock”模式下,我们只是简单地做一些常规的 setitimer 事情,它发送信号给进程。所以内核应该选择线程,在实践中和所有已知的操作系统上,它倾向于选择当前正在运行的线程。但是有一个问题,那就是当进程同时在多个内核上运行时,无论 CPU 核算和定时器过期代码都会严重扭曲所选择的线程。

我看到在实践中,当多个线程长时间运行时会发生这种情况。不知何故,在 Google 的产品中(至少对于我处理的用户服务系统而言),没有偏斜。 IE。至少在某些情况下,这在实践中似乎没什么大不了的。

更多细节在这里:https://github.com/golang/go/issues/14434

即这个(默认情况下未启用)per_thread_timer_enabled_ 模式是专门为尝试处理此问题而构建的。但要使其库存有困难。 (我欢迎任何建议或其他贡献)

© www.soinside.com 2019 - 2024. All rights reserved.