Python性能分析工具

本文主要讲了如何使用 timeperfline_profiler

测试python文件

call.py

def call():
    return True

for i in range(10000000):
    call()

time使用

time python call.py

  • real 总耗时 1.488秒
  • user 用户态耗时 1.255 秒
  • sys 内核态耗时0.230秒

time

perf使用

perf --help 之后可以看到perf的二级命令。

序号 命令 作用
1 annotate 解析perf record生成的perf.data文件,显示被注释的代码。
2 archive 根据数据文件记录的build-id,将所有被采样到的elf文件打包。利用此压缩包,可以再任何机器上分析数据文件中记录的采样数据。
3 bench perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。
4 buildid-cache 管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。buildid被perf用来关联性能数据与elf文件。
5 buildid-list 列出数据文件中记录的所有buildid。
6 diff 对比两个数据文件的差异。能够给出每个符号(函数)在热点分析上的具体差异。
7 evlist 列出数据文件perf.data中所有性能事件。
8 inject 该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。
9 kmem 针对内核内存(slab)子系统进行追踪测量的工具
10 kvm 用来追踪测试运行在KVM虚拟机上的Guest OS。
11 list 列出当前系统支持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。
12 lock 分析内核中的锁信息,包括锁的争用情况,等待延迟等。
13 mem 内存存取情况
14 record 收集采样信息,并将其记录在数据文件中。随后可通过其它工具对数据文件进行分析。
15 report 读取perf record创建的数据文件,并给出热点分析结果。
16 sched 针对调度器子系统的分析工具。
17 script 执行perl或python写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等。
18 stat 执行某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等。
19 test perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。
20 timechart 针对测试期间系统行为进行可视化的工具
21 top 类似于linux的top命令,对系统性能进行实时分析。
22 trace 关于syscall的工具。
23 probe 用于定义动态检查点。

全局性概况:

perf list 查看当前系统支持的性能事件;

perf bench 对系统性能进行摸底;

perf test 对系统进行健全性测试;

perf stat 对全局性能进行统计;

全局细节:

perf top 可以实时查看当前系统进程函数占用率情况;

perf probe 可以自定义动态事件;

特定功能分析:

perf kmem 针对slab子系统性能分析;

perf kvm 针对kvm虚拟化分析;

perf lock 分析锁性能;

perf mem 分析内存slab性能;

perf sched 分析内核调度器性能;

perf trace 记录系统调用轨迹;

最常用功能perf record,可以系统全局,也可以具体到某个进程,更甚具体到某一进程某一事件;可宏观,也可以很微观。

perf record –e cpu-clock python call.py
pref record 记录信息到perf.data;

perf report 生成报告;

perf diff 对两个记录进行diff;

perf evlist 列出记录的性能事件;

perf annotate 显示perf.data函数代码;

perf archive 将相关符号打包,方便在其它机器进行分析;

perf script 将perf.data输出可读性文本;

可视化工具perf timechart

perf timechart record记录事件;

perf timechart生成output.svg文档;

关于perf top界面常用命令如下:

h:显示帮助,即可显示详细的帮助信息。

UP/DOWN/PGUP/PGDN/SPACE:上下和翻页。

a:annotate current symbol,注解当前符号。能够给出汇编语言的注解,给出各条指令的采样率。

d:过滤掉所有不属于此DSO的符号。非常方便查看同一类别的符号。

P:将当前信息保存到perf.hist.N中。

perf top常用选项有:

-e :指明要分析的性能事件。

-p :Profile events on existing Process ID (comma sperated list). 仅分析目标进程及其创建的线程。

-k :Path to vmlinux. Required for annotation functionality. 带符号表的内核映像所在的路径。

-K:不显示属于内核或模块的符号。

-U:不显示属于用户态程序的符号。

-d :界面的刷新周期,默认为2s,因为perf top默认每2s从mmap的内存区域读取一次性能数据。

-g:得到函数的调用关系图。

perf top --call-graph [fractal],路径概率为相对值,加起来为100%,调用顺序为从下往上。

perf top --call-graph graph,路径概率为绝对值,加起来为该函数的热度。

image

perf stat

perf stat用于运行指令,并分析其统计结果。虽然perf top也可以指定pid,但是必须先启动应用才能查看信息。

perf stat能完整统计应用整个生命周期的信息。

命令格式为:

perf stat [-e | --event=EVENT] [-a]
perf stat [-e | --event=EVENT] [-a] — []

下面简单看一下perf stat 的输出:

[root@master ~]# perf stat
Performance counter stats for 'system wide':

40904.820871 cpu-clock (msec) # 5.000 CPUs utilized
18,132 context-switches # 0.443 K/sec
1,053 cpu-migrations # 0.026 K/sec
2,420 page-faults # 0.059 K/sec
3,958,376,712 cycles # 0.097 GHz (49.99%)
574,598,403 stalled-cycles-frontend # 14.52% frontend cycles idle (49.98%)
9,392,982,910 stalled-cycles-backend # 237.29% backend cycles idle (50.00%)
1,653,185,883 instructions # 0.42 insn per cycle
# 5.68 stalled cycles per insn (50.01%)
237,061,366 branches # 5.795 M/sec (50.02%)
18,333,168 branch-misses # 7.73% of all branches (50.00%)

​ 8.181521203 seconds time elapsed

输出解释如下:

cpu-clock:任务真正占用的处理器时间,单位为ms。CPUs utilized = task-clock / time elapsed,CPU的占用率。

context-switches:程序在运行过程中上下文的切换次数。

CPU-migrations:程序在运行过程中发生的处理器迁移次数。Linux为了维持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU迁移到另一个CPU。

CPU迁移和上下文切换:发生上下文切换不一定会发生CPU迁移,而发生CPU迁移时肯定会发生上下文切换。发生上下文切换有可能只是把上下文从当前CPU中换出,下一次调度器还是将进程安排在这个CPU上执行。

page-faults:缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中,或者请求的页面虽然在内存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页异常。另外TLB不命中,页面访问权限不匹配等情况也会触发缺页异常。

cycles:消耗的处理器周期数。如果把被ls使用的cpu cycles看成是一个处理器的,那么它的主频为2.486GHz。可以用cycles / task-clock算出。

stalled-cycles-frontend:指令读取或解码的质量步骤,未能按理想状态发挥并行左右,发生停滞的时钟周期。

stalled-cycles-backend:指令执行步骤,发生停滞的时钟周期。

instructions:执行了多少条指令。IPC为平均每个cpu cycle执行了多少条指令。

branches:遇到的分支指令数。branch-misses是预测错误的分支指令数。

其他常用参数

-a, --all-cpus 显示所有CPU上的统计信息
-C, --cpu 显示指定CPU的统计信息
-c, --scale scale/normalize counters
-D, --delay ms to wait before starting measurement after program start
-d, --detailed detailed run - start a lot of events
-e, --event event selector. use 'perf list' to list available events
-G, --cgroup monitor event in cgroup name only
-g, --group put the counters into a counter group
-I, --interval-print
print counts at regular interval in ms (>= 10)
-i, --no-inherit child tasks do not inherit counters
-n, --null null run - dont start any counters
-o, --output 输出统计信息到文件
-p, --pid stat events on existing process id
-r, --repeat repeat command and print average + stddev (max: 100, forever: 0)
-S, --sync call sync() before starting a run
-t, --tid stat events on existing thread id
...

示例

前面统计程序的示例,下面看一下统计CPU信息的示例:

perf stat python call.py

image

perf top -C 0

image

Flame Graph

FlameGraph

1.抓取perf信息并转换

perf record -F 99 -a -g -- sleep 60
perf script > out.perf
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.kern_folded > kernel.svg

line_profiler使用

逐行分析python代码

# test.py
import line_profiler

@profile
def fib(n):
    # 文件名aaa.py
    a, b = 0, 1
    for i in range(0, n):
        a, b = b, a+b
    return a
fib(5)

D:\PythonProject\interview> kernprof -l -v test.py

Wrote profile results to test.py.lprof
Timer unit: 1e-06 s

Total time: 3.61e-05 s
File: test.py
Function: fib at line 253

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   253                                           @profile
   254                                           def fib(n):
   255                                               # 文件名aaa.py
   256         1         15.3     15.3     42.4      a, b = 0, 1
   257         6          4.0      0.7     11.1      for i in range(0, n):
   258         5         16.4      3.3     45.4          a, b = b, a+b
   259         1          0.4      0.4      1.1      return a

  • Total Time:测试代码的总运行时间
  • Line:代码行号
  • Hits:表示每行代码运行的次数
  • Time:每行代码运行的总时间
  • Per Hits:每行代码运行一次的时间
  • % Time:每行代码运行时间的百分比
  • 从分析结果可以看出:第258行代码运行时间最长

参考资料

系统级性能分析工具 — Perf:http://blog.csdn.net/zhangskd/article/details/37902159/

posted @ 2022-02-06 13:56  TY520  阅读(1810)  评论(0编辑  收藏  举报