分析python C扩展

pyg*_*iel 36 c python profiling

我开发了一个python C扩展,它从python接收数据并计算一些cpu密集型计算.可以分析C扩展吗?

这里的问题是在C中编写样本测试以进行分析将是一项挑战,因为代码依赖于特定的输入和数据结构(由python控制代码生成).

你有什么建议吗?

Fab*_*osa 27

在pygabriel发表评论之后,我决定使用google-perftools的cpu-profiler将一个包上传到pypi,该pypi为python扩展实现了一个探查器:http://pypi.python.org/pypi/yep


pyg*_*iel 19

我找到了使用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()
Run Code Online (Sandbox Code Playgroud)

然后分析例如你可以用callgrind格式导出并在kcachegrind中看到结果:

pprof --callgrind c_extension.so output.prof > output.callgrind 
kcachegrind output.callgrind
Run Code Online (Sandbox Code Playgroud)


Ham*_*mer 7

我发现py-spy非常容易使用。有关其本机扩展支持的说明,请参阅此博客文章。

强调:

  • 可点安装
  • 基于CPU采样
  • 不需要编译器标志
  • 执行您的程序或附加到正在运行的进程
  • 多种输出格式(我推荐--format speedscope
  • 可配置的采样率

  • 这应该是最重要的答案! (2认同)

som*_*may 5

我的一位同事告诉我 ltrace(1)。在同样的情况下,它对我帮助很大。

假设您的 C 扩展的共享对象名称是myext.so并且您想要执行benchmark.py,然后

ltrace -x @myext.so -c python benchmark.py
Run Code Online (Sandbox Code Playgroud)

它的输出就像

% 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
....
Run Code Online (Sandbox Code Playgroud)

如果您的共享对象在其文件名中有-+,则需要特别小心。这些字符不会按原样处理(请参阅man 1 ltrace有关详细信息,)。

通配符*可以是一种解决方法,例如-x @myext*代替-x @myext-2.so.