【发布时间】:2011-02-06 14:14:48
【问题描述】:
我开发了一个 python C 扩展,它从 python 接收数据并计算一些 cpu 密集型计算。 可以分析 C 扩展名吗?
这里的问题是,用 C 语言编写一个要分析的示例测试会很有挑战性,因为代码依赖于特定的输入和数据结构(由 python 控制代码生成)。
你有什么建议吗?
【问题讨论】:
我开发了一个 python C 扩展,它从 python 接收数据并计算一些 cpu 密集型计算。 可以分析 C 扩展名吗?
这里的问题是,用 C 语言编写一个要分析的示例测试会很有挑战性,因为代码依赖于特定的输入和数据结构(由 python 控制代码生成)。
你有什么建议吗?
【问题讨论】:
我发现py-spy 非常易于使用。有关其原生扩展支持的说明,请参阅 this blog post。
亮点:
--format speedscope)【讨论】:
我的一位同事告诉我ltrace(1)。在同样的情况下,它对我帮助很大。
假设你的C扩展的共享对象名是myext.so,你要执行benchmark.py,那么
ltrace -x @myext.so -c python benchmark.py
它的输出是这样的
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
24.88 30.202126 7550531 4 ldap_result
12.46 15.117625 7558812 2 l_ldap_result4
12.41 15.059652 5019884 3 ldap_chase_v3referrals
12.41 15.057678 3764419 4 ldap_new_connection
12.40 15.050310 3762577 4 ldap_int_open_connection
12.39 15.042360 3008472 5 ldap_send_server_request
12.38 15.029055 3757263 4 ldap_connect_to_host
0.05 0.057890 28945 2 ldap_get_option
0.04 0.052182 26091 2 ldap_sasl_bind
0.03 0.030760 30760 1 l_ldap_get_option
0.03 0.030635 30635 1 LDAP_get_option
0.02 0.029960 14980 2 ldap_initialize
0.02 0.027988 27988 1 ldap_int_initialize
0.02 0.026722 26722 1 l_ldap_simple_bind
0.02 0.026386 13193 2 ldap_send_initial_request
0.02 0.025810 12905 2 ldap_int_select
....
如果您的共享对象的文件名中有- 或+,则需要特别小心。这些字符不会按原样处理(有关详细信息,请参阅man 1 ltrace)。
通配符* 可以是一种解决方法,例如-x @myext* 代替-x @myext-2.so。
【讨论】:
我找到了使用google-perftools 的方法。诀窍是将函数 StartProfiler 和 StopProfiler 包装在 python 中(在我的例子中是通过 cython)。
要分析 C 扩展,足以将 python 代码包装在 StartProfiler 和 StopProfiler 调用中。
from google_perftools_wrapped import StartProfiler, StopProfiler
import c_extension # extension to profile c_extension.so
StartProfiler("output.prof")
... calling the interesting functions from the C extension module ...
StopProfiler()
然后进行分析,例如您可以以 callgrind 格式导出并在 kcachegrind 中查看结果:
pprof --callgrind c_extension.so output.prof > output.callgrind
kcachegrind output.callgrind
【讨论】:
在 pygabriel 发表评论后,我决定将一个包上传到 pypi,该包使用来自 google-perftools 的 cpu-profiler 实现 python 扩展的分析器:http://pypi.python.org/pypi/yep
【讨论】:
使用gprof,您可以分析任何properly compiled 并链接的程序(gcc -pg 等,在gprof 的情况下)。如果您使用的 Python 版本不是使用 gcc 构建的(例如,PSF 分发的 Windows 预编译版本),您需要研究该平台和工具链存在哪些等效工具(在 Windows PSF 的情况下,可能是 @ 987654326@可以帮忙)。那里可能有“不相关”的数据(Python 运行时中的内部 C 函数),如果是这样,gprof 显示的百分比可能不适用——但绝对数量(调用次数及其持续时间)仍然存在有效,并且您可以对gprof 的输出进行后处理(例如,使用一点 Python 脚本;-)以排除不相关的数据并计算您想要的百分比。
【讨论】: