几年前,当我在Despegar工作时,我编写了一个小python脚本,它帮助我观察和识别与 CPU 使用相关的问题。

GitHub 徽标cspietta/顶级线程

一个微型命令行工具,提供给定进程的活动线程的动态实时视图,包括 CPU、磁盘和调度的统计信息。

它是一个用户友好的命令行界面,提供给定进程的活动线程的动态实时视图,包括 CPU、磁盘和_调度_的统计信息。

使其真正强大的指标是与调度相关的指标:花费在 cpu / runqueue 上的时间。

为什么?

在某些情况下,知道线程花了多少时间_试图进入 CPU_,而不是_在 CPU_ 上,这很有趣。此类信息可以通过perf和BCC等跟踪工具轻松获得,但这些工具需要 root 权限,这在生产服务器中通常不可用,因此您无法使用它们进行故障排除。

怎么了?

我最终在Python中开发了一个脚本,它允许我通过读取/proc/{pid}/schedstat文件实时可视化_每个任务的运行队列延迟_。

事实上,它显示了一些额外的统计数据:

  • CPU 使用率:total%usr%system%guest%wait

  • 磁盘使用量:每秒读取 kB 每秒写入 kB

  • 调度程序统计信息:

  • 在 CPU 上花费的时间。

  • 等待运行队列所花费的时间(runqueue latency)

  • 当前 CPU 上运行的 timeslices 数量。

  • Java 详细信息:如果目标是可以附加jstack的 Java 进程,则会显示一些额外的详细信息,例如线程名称和堆栈跟踪。

这个需要:

  • Python 3

  • 系统统计

它仅适用于Linux,因为它使用/proc/{pid}/schedstat来获取调度统计信息。

怎么用?

我将代码保存在一个文件中,因此就像下载脚本一样简单:

wget -O top_threads.py 'https://github.com/cspinetta/top-threads/releases/download/0.0.1/top_threads.py' \
  && chmod +x top_threads.py

进入全屏模式 退出全屏模式

用法示例:

# watch <pid>'s threads with default values
./top_threads.py -p <pid>

# print output in the terminal
./top_threads.py -p <pid> --display terminal

# sorting by run queue latency
./top_threads.py -p <pid> --sort rq

# in case a java process, change the number of stack traces to display
./top_threads.py -p <pid> --max-stack-depth 10

# enable debug log for troubleshooting
./top_threads.py -p <pid> --debug

进入全屏模式 退出全屏模式

要记住的一些事情:

  • 第一个输出是进程第一次执行的统计信息。

  • --display refresh提供类似于topwatch(默认)的视图,而terminal在终端中的每次迭代中打印输出,如pidstat

这个工具有什么好的用例?

当我必须在线程级别分析性能问题并且想要检查 CPU 或磁盘的动态使用情况时,我经常使用此脚本。

这个工具可以帮助我回答一些问题:

  • 哪个线程正在吃掉整个 CPU?

  • 线程等待占用 CPU 多长时间?

  • 现在哪些线程正在使用磁盘?

图片中的示例

  • --display refresh(默认值):

[Top Java Threads Refresh](https://res.cloudinary.com/practicaldev/image/fetch/s--m2MC67gj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/228lkptniqw0jp8syx49.png)

  • --display terminal:

[![终端]中的顶级 Java 线程(https://res.cloudinary.com/practicaldev/image/fetch/s--_KXETflm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r3pbcs11uzd1d4okvjds.png)](https://res.cloudinary.com/practicaldev/image/fetch/s--_KXETflm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/i/r3pbcs11uzd1d4okvjds.png)

用途

usage: top_threads.py [-h] -p PID [-n [NUMBER]]
                      [--max-stack-depth [STACK_SIZE]]
                      [--sort [{cpu,rq,disk,disk-rd,disk-wr}]]
                      [--display [{terminal,refresh}]] [--no-jstack] [--debug]

Tool for analysing active Threads

optional arguments:
  -h, --help            show this help message and exit
  -p PID                Process ID
  -n [NUMBER]           Number of threads to show per sample. Default: 10
  --max-stack-depth [STACK_SIZE], -m [STACK_SIZE]
                        Max number of stack frames (only when jstack can be
                        used). Default: 1
  --sort [{cpu,rq,disk,disk-rd,disk-wr}], -s [{cpu,rq,disk,disk-rd,disk-wr}]
                        Field used for sorting. Default: cpu
  --display [{terminal,refresh}], -d [{terminal,refresh}]
                        Select the way to display the info: terminal or
                        refresh. Default: refresh
  --no-jstack           Turn off usage of jstack to retrieve thread info like
                        name and stack
  --debug               Turn on logs for debugging purposes

进入全屏模式 退出全屏模式

Logo

更多推荐