跳转到主要内容

从几个分析器的输出生成.dot图形。

项目描述

关于 gprof2dot

这是一个Python脚本,可以将多个分析器的输出转换为dot图形

它可以

如果您想要查看由gprof2dot生成的图形的交互式查看器,请查看xdot.py

状态

gprof2dot 目前满足了我的需求,我几乎没有时间维护它。因此,我恐怕任何请求的功能都不太可能实现,我处理问题报告或拉取请求可能会很慢。

Build Status codecov

示例

这是默认设置下的 示例数据,来自 Linux Gazette 文章

Sample

需求

  • Python:已知与版本 >=3.8 兼容;它很可能不会与更早的版本兼容。
  • Graphviz:已测试与版本 2.26.3 兼容,但应该与其他版本也兼容。

Windows 用户

Linux 用户

在 Debian/Ubuntu 上运行

apt-get install python3 graphviz

在 RedHat/Fedora 上运行

yum install python3 graphviz

下载

文档

使用方法

Usage: 
	gprof2dot.py [options] [file] ...

Options:
  -h, --help            show this help message and exit
  -o FILE, --output=FILE
                        output filename [stdout]
  -n PERCENTAGE, --node-thres=PERCENTAGE
                        eliminate nodes below this threshold [default: 0.5]
  -e PERCENTAGE, --edge-thres=PERCENTAGE
                        eliminate edges below this threshold [default: 0.1]
  -f FORMAT, --format=FORMAT
                        profile format: axe, callgrind, collapse, dtrace,
                        hprof, json, oprofile, perf, prof, pstats, sleepy,
                        sysprof or xperf [default: prof]
  --total=TOTALMETHOD   preferred method of calculating total time: callratios
                        or callstacks (currently affects only perf format)
                        [default: callratios]
  -c THEME, --colormap=THEME
                        color map: bw, color, gray, pink or print [default:
                        color]
  -s, --strip           strip function parameters, template parameters, and
                        const modifiers from demangled C++ function names
  --color-nodes-by-selftime
                        color nodes by self time, rather than by total time
                        (sum of self and descendants)
  -w, --wrap            wrap function names
  --show-samples        show function samples
  --node-label=MEASURE  measurements to on show the node (can be specified
                        multiple times): self-time, self-time-percentage,
                        total-time or total-time-percentage [default: total-
                        time-percentage, self-time-percentage]
  --list-functions=LIST_FUNCTIONS
                        list functions available for selection in -z or -l,
                        requires selector argument ( use '+' to select all).
                        Recall that the selector argument is used with
                        Unix/Bash globbing/pattern matching, and that entries
                        are formatted '<pkg>:<linenum>:<function>'. When
                        argument starts with '%', a dump of all available
                        information is performed for selected entries,  after
                        removal of leading '%'.
  -z ROOT, --root=ROOT  prune call graph to show only descendants of specified
                        root function
  -l LEAF, --leaf=LEAF  prune call graph to show only ancestors of specified
                        leaf function
  --depth=DEPTH         prune call graph to show only descendants or ancestors
                        until specified depth
  --skew=THEME_SKEW     skew the colorization curve.  Values < 1.0 give more
                        variety to lower percentages.  Values > 1.0 give less
                        variety to lower percentages
  -p FILTER_PATHS, --path=FILTER_PATHS
                        Filter all modules not in a specified path

示例

Linux perf

perf record -g -- /path/to/your/executable
perf script | c++filt | gprof2dot.py -f perf | dot -Tpng -o output.png

oprofile

opcontrol --callgraph=16
opcontrol --start
/path/to/your/executable arg1 arg2
opcontrol --stop
opcontrol --dump
opreport -cgf | gprof2dot.py -f oprofile | dot -Tpng -o output.png

xperf

如果你不熟悉 xperf,请先阅读 这篇文章。然后执行以下操作:

  • 以以下方式启动 xperf:

    xperf -on Latency -stackwalk profile
    
  • 运行你的应用程序。

  • 保存数据。` xperf -d output.etl

  • 启动可视化器

    xperf output.etl
    
  • 跟踪 菜单中,选择 加载符号。如果需要,请配置 符号路径

  • CPU 样本图 上选择感兴趣的区域,右键单击,然后选择 摘要表

  • 菜单中,确保 堆栈 列已启用且可见。

  • 右键单击一行,选择 导出完整表格,并保存到 output.csv

  • 然后以以下方式调用 gprof2dot:

    gprof2dot.py -f xperf output.csv | dot -Tpng -o output.png
    

VTune Amplifier XE

  • 以以下方式收集配置文件数据(也可以从 GUI 中执行)

    amplxe-cl -collect hotspots -result-dir output -- your-app
    
  • 以以下方式可视化配置文件数据

    amplxe-cl -report gprof-cc -result-dir output -format text -report-output output.txt
    gprof2dot.py -f axe output.txt | dot -Tpng -o output.png
    

另请参阅 Kirill Rogozhin 的博客文章

gprof

/path/to/your/executable arg1 arg2
gprof path/to/your/executable | gprof2dot.py | dot -Tpng -o output.png

python profile

python -m profile -o output.pstats path/to/your/script arg1 arg2
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png

python cProfile(以前称为 lsprof)

python -m cProfile -o output.pstats path/to/your/script arg1 arg2
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png

Java HPROF

java -agentlib:hprof=cpu=samples ...
gprof2dot.py -f hprof java.hprof.txt | dot -Tpng -o output.png

有关详细信息,请参阅 Russell Power 的博客文章

DTrace

dtrace -x ustackframes=100 -n 'profile-97 /pid == 12345/ { @[ustack()] = count(); } tick-60s { exit(0); }' -o out.user_stacks
gprof2dot.py -f dtrace out.user_stacks | dot -Tpng -o output.png

# Notice: sometimes, the dtrace outputs format may be latin-1, and gprof2dot will fail to parse it.
# To solve this problem, you should use iconv to convert to UTF-8 explicitly.
# TODO: add an encoding flag to tell gprof2dot how to decode the profile file.
iconv -f ISO-8859-1 -t UTF-8 out.user_stacks | gprof2dot.py -f dtrace

stackcollapse

Brendan Gregg 的 FlameGraph 工具以每行一个样本的文本文件作为输入。此格式可以通过使用 FlameGraph 仓库中的 stackcollapse 脚本 从其他各种输入生成。它也可以由如 py-spy 之类的工具生成。

示例用法

  • Perf

    perf record -g -- /path/to/your/executable
    perf script | FlameGraph/stackcollapse-perf.pl > out.collapse
    gprof2dot.py -f collapse out.collapse | dot -Tpng -o output.png
    
  • Py-spy

    py-spy record -p <pidfile> -f raw -o out.collapse
    gprof2dot.py -f collapse out.collapse | dot -Tpng -o output.png
    

输出

输出图中的一个节点代表一个函数,具有以下布局

+------------------------------+
|        function name         |
| total time % ( self time % ) |
|         total calls          |
+------------------------------+

其中

  • 总时间百分比 是在该函数及其所有子函数中花费的运行时间百分比;
  • 自时间百分比 是仅在该函数中花费的运行时间百分比;
  • 总调用次数 是调用此函数的总次数(包括递归调用)。

一个边代表两个函数之间的调用,具有以下布局

           total time %
              calls
parent --------------------> children

其中

  • 总时间百分比 是从子函数传输到父函数的运行时间百分比(如果可用);
  • 调用次数 是父函数调用子函数的次数。

请注意,在递归循环中,节点中的 总时间百分比 对于循环中的所有函数都是相同的,循环内部的边中没有 总时间百分比 数值,因为这样的数值没有意义。

节点和边的颜色根据总时间%值而变化。在默认的温度类似颜色映射中,花费大部分时间的函数(热点)标记为饱和红色,而花费很少时间的函数标记为深蓝色。请注意,默认情况下不显示花费可忽略或没有时间的函数。

函数列表

标志--list-functions允许列出在gprof输入中找到的函数条目。这被用作与--leaf-l)或--root-z)标志一起使用的工具。

prof2dot.py -f pstats /tmp/myLog.profile  --list-functions "test_segments:*:*" 
  
test_segments:5:<module>,
test_segments:206:TestSegments,
test_segments:46:<lambda>
  • 选择器参数与Unix/Bash通配符/模式匹配一起使用,与-l-z标志执行的方式相同。

  • 条目格式为'<pkg>:<linenum>:<function>'。

  • 当选择器参数以'%'开头时,执行所有选择条目的信息转储,在去除选择器前面的'%'后。如果选择器是"+"或"*",则打印出函数的完整列表。

常见问题解答

如何生成完整的调用图?

默认情况下,gprof2dot.py生成一个部分调用图,排除在总计算时间中有小或没有影响的节点和边。如果您想生成完整的调用图,请通过-n / --node-thres-e / --edge-thres选项设置节点和边的零阈值,如下所示:

gprof2dot.py -n0 -e0

节点标签太宽。如何缩小它们?

当分析C++代码时,节点标签可能会变得非常宽,这是由于在未解析的C++函数名中包含作用域、函数参数和模板参数。

如果您不需要函数和模板参数信息,则通过传递-s / --strip选项来删除它们。

如果您想保留所有这些信息,或者标签仍然太宽,则可以通过传递-w / --wrap来包装标签。请注意,由于dot不会自动包装标签,标签边距可能不会完全对齐。

为什么没有输出,或者它都是同一种颜色?

可能是因为总的执行时间太短,所以配置文件中没有足够的精度来确定时间在哪里被花费。

您仍然可以通过通过设置节点和边的零阈值来强制显示整个图,如下所示:

gprof2dot.py -n0 -e0

但为了得到有意义的成果,您将需要找到一种方法来运行程序更长的时间(从多次运行中汇总结果)。

为什么百分比不总和?

您可能有一个执行时间太短,导致舍入误差很大。

请参阅上面关于增加执行时间的问题。

当为分析编译时,我应该传递哪些gcc选项?

产生合适结果所必需的选项是

  • -g : 生成调试信息
  • -fno-omit-frame-pointer : 使用帧指针(在某些架构(如x86_64)和一些优化级别中默认禁用帧指针使用;没有它无法遍历调用栈)

如果您使用gprof,还需要-pg选项,但现在您可以使用其他许多分析工具获得更好的结果,其中大多数在编译时不需要特殊的代码检查。

您想要分析的代码尽可能接近您将发布的代码。所以您应该包含在发布代码中使用的所有选项,通常

  • -O2 : 不涉及空间-速度权衡的优化
  • -DNDEBUG : 禁用标准库中的调试代码(如assert宏)

尽管gcc执行了许多优化,但这些优化会干扰分析结果的准确性/粒度。您应该传递这些选项以禁用特定的优化。

  • -fno-inline-functions:不要将函数内联到其父函数中(否则这些函数花费的时间将归因于调用者)
  • -fno-inline-functions-called-once:类似于上面
  • -fno-optimize-sibling-calls:不要优化兄弟和尾递归调用(否则尾递归调用可能会归因于父函数)

如果粒度仍然太低,您可以通过传递这些选项来获得更细的粒度

  • -fno-default-inline:不要默认将成员函数内联,仅仅因为它们在类作用域内定义
  • -fno-inline:不要注意内联关键字。然而,请注意,使用这些最后的选项,调用多次的函数的计时可能会因为函数调用开销而失真。这对于典型的C++代码尤其如此,这些代码期望进行这些优化以获得良好的性能。

有关gcc优化选项的完整列表,请参阅更多信息

链接

有关外部资源,包括补充/替代工具,请参阅wiki

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面