我開發了一個python C擴展,它接收來自python的數據並計算一些cpu密集計算。 可以剖析C-extension?剖析python C擴展
這裏的問題是在C中編寫樣本測試需要進行分析,因爲代碼依賴於特定輸入和數據結構(由python控制代碼生成),所以具有挑戰性。
你有什麼建議嗎?
我開發了一個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
與gprof,你可以分析任何程序是properly compiled和鏈接(gcc -pg
等,在gprof
的情況下)。如果您使用的不是gcc
(例如,PSF分發的Windows預編譯版本)構建的Python版本,則需要研究該平臺和工具鏈存在的等效工具(在Windows PSF的情況下,可能mingw
可以幫助您)。那裏可能存在「不相關的」數據(Python運行時的內部C函數),如果是這樣,gprof
所示的百分比可能不適用 - 但是絕對數量(呼叫和持續時間)仍然有效,你可以後處理gprof
的輸出(例如,用一個小小的Python腳本;-)來排除不相關的數據並計算你想要的百分比。
我仍然有一些使用這個問題,但也許這只是我的錯。 編譯並鏈接(gcc)python源文件後,可執行文件正確生成gmon.out文件。 如果我執行加載用-pg標誌編譯的C擴展(* .so)的腳本,則會生成分析輸出(gprof/path/custom/python或gprof擴展。所以)不顯示包含在C庫中的函數調用。 我錯過了什麼? – pygabriel 2010-04-11 19:08:44
gprof不能和dlopen()很好地玩,大概是因爲它在加載庫之前初始化它的內存映射。如果主機可執行文件(在本例中爲python)沒有直接與.so文件相鏈接,那麼僅使用-pg標誌進行編譯並不能幫助gprof。 – 2013-02-07 22:05:42
由pygabriel的評論後,我決定上傳一個包的PyPI實現分析器爲python擴展使用谷歌perftools中的cpu-profiler:http://pypi.python.org/pypi/yep
謝謝,我發現這非常有用,並且很容易與之合作! – robince 2011-03-15 20:29:51
謝謝Fabian,希望這可以做到! – 2013-02-07 22:08:16
是否也是配置文件內存使用情況? – 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
。
非常感謝你的提示!我實際上是在尋找同樣的事情。我會嘗試。 – ThR37 2010-10-07 14:35:23
編輯:它確實工作得很好!即使我在CPU分析期間有時會出現段錯誤(但是這是「正常」並在文檔中解釋過...我正在使用x86_64 :() – ThR37 2010-10-07 15:28:28
非常感謝您爲這個小塊塊。非常非常有用:-)我所看到的是pprof(或者說Debian軟件包中的google-pprof),就是我沒有像分析相同代碼時那樣去除儘可能多的符號與valgrind。可能是我編譯時需要指定-pg嗎? – miquelramirez 2013-08-20 06:29:34