剖析python C扩展

问题描述:

我开发了一个python C扩展,它接收来自python的数据并计算一些cpu密集计算。 可以剖析C-extension?剖析python C扩展

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

你有什么建议吗?

我发现我的方式使用google-perftools。诀窍是在Python中包装函数StartProfiler和StopProfiler(在我的情况下,通过cython)。

要剖析C扩展就足以将Python代码包装在StartProfiler和StopProfiler调用中。

from google_perftools_wrapped import StartProfiler, StopProfiler 
impor 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 
+0

非常感谢你的提示!我实际上是在寻找同样的事情。我会尝试。 – ThR37 2010-10-07 14:35:23

+0

编辑:它确实工作得很好!即使我在CPU分析期间有时会出现段错误(但是这是“正常”并在文档中解释过...我正在使用x86_64 :() – ThR37 2010-10-07 15:28:28

+0

非常感谢您为这个小块块。非常非常有用:-)我所看到的是pprof(或者说Debian软件包中的google-pprof),就是我没有像分析相同代码时那样去除尽可能多的符号与valgrind。可能是我编译时需要指定-pg吗? – miquelramirez 2013-08-20 06:29:34

gprof,你可以分析任何程序是properly compiled和链接(gcc -pg等,在gprof的情况下)。如果您使用的不是gcc(例如,PSF分发的Windows预编译版本)构建的Python版本,则需要研究该平台和工具链存在的等效工具(在Windows PSF的情况下,可能mingw可以帮助您)。那里可能存在“不相关的”数据(Python运行时的内部C函数),如果是这样,gprof所示的百分比可能不适用 - 但是绝对数量(呼叫和持续时间)仍然有效,你可以后处理gprof的输出(例如,用一个小小的Python脚本;-)来排除不相关的数据并计算你想要的百分比。

+1

我仍然有一些使用这个问题,但也许这只是我的错。 编译并链接(gcc)python源文件后,可执行文件正确生成gmon.out文件。 如果我执行加载用-pg标志编译的C扩展(* .so)的脚本,则会生成分析输出(gprof/path/custom/python或gprof扩展。所以)不显示包含在C库中的函数调用。 我错过了什么? – pygabriel 2010-04-11 19:08:44

+2

gprof不能和dlopen()很好地玩,大概是因为它在加载库之前初始化它的内存映射。如果主机可执行文件(在本例中为python)没有直接与.so文件相链接,那么仅使用-pg标志进行编译并不能帮助gprof。 – 2013-02-07 22:05:42

由pygabriel的评论后,我决定上传一个包的PyPI实现分析器为python扩展使用谷歌perftools中的cpu-profiler:http://pypi.python.org/pypi/yep

+0

谢谢,我发现这非常有用,并且很容易与之合作! – robince 2011-03-15 20:29:51

+0

谢谢F*,希望这可以做到! – 2013-02-07 22:08:16

+0

是否也是配置文件内存使用情况? – 2015-08-05 15:28:55

我的一位同事告诉我ltrace(1)。它在相同的情况下帮了我很多。

假设你的C extention的共享对象的名字是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 ltrace(1))。

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