2010-04-10 125 views
30

我開發了一個python C擴展,它接收來自python的數據並計算一些cpu密集計算。 可以剖析C-extension?剖析python C擴展

這裏的問題是在C中編寫樣本測試需要進行分析,因爲代碼依賴於特定輸入和數據結構(由python控制代碼生成),所以具有挑戰性。

你有什麼建議嗎?

回答

17

我發現我的方式使用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

4

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

22

由pygabriel的評論後,我決定上傳一個包的PyPI實現分析器爲python擴展使用谷歌perftools中的cpu-profiler:http://pypi.python.org/pypi/yep

+0

謝謝,我發現這非常有用,並且很容易與之合作! – robince 2011-03-15 20:29:51

+0

謝謝Fabian,希望這可以做到! – 2013-02-07 22:08:16

+0

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

0

我的一位同事告訴我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