2015-11-09 64 views
0

我有以下Cython代碼:探查的用Cython代碼

# cython: profile=True 
import cProfile 
from cython import parallel 
from libc.stdio cimport FILE, fopen, fclose, fwrite, getline, printf 
from libc.string cimport strlen 
from libcpp.string cimport string 
cdef extern from "stdio.h" nogil: 
    int mkstemp(char*); 

cdef run_io(string obj): 
    cdef int i, dump 
    cdef size_t len_ = 0 
    cdef char* fname = "/tmp/tmpc_XXXXXX" 
    cdef char* nullchar = NULL 
    cdef char* line = NULL 
    cdef string content = b"" 
    cdef FILE* cfile 
    for i in range(10000): 
     dump = mkstemp(fname) 
     cfile = fopen(fname, "wb") 
     fwrite(obj.data(), 1, obj.size(), cfile) 
     fclose(cfile) 
     cfile = fopen(fname, "rb") 
     while True: 
      if getline(&line, &len_, cfile) == -1: 
       break 
      else: 
       content.append(line) 
     fclose(cfile) 

def run_test(): 
    cdef string obj = b"abc\ndef" 
    cProfile.runctx("run_io(obj)", globals(), locals()) 

當我嘗試從一個python3控制檯運行它,我得到的錯誤:

NameError: name 'run_io' is not defined 

如果我在清晰度改變run_io功能cdefdef,它的工作原理:

  7 function calls in 2.400 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 2.400 2.400 <string>:1(<module>) 
     2 0.000 0.000 0.000 0.000 stringsource:13(__pyx_convert_string_from_py_std__in_string) 
     1 2.400 2.400 2.400 2.400 testc2.pyx:10(run_io) 
     1 0.000 0.000 2.400 2.400 {built-in method exec} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     1 0.000 0.000 2.400 2.400 {test.run_io} 

但是,這並不是很豐富,因爲我只看到了整個函數的總運行時間(我希望看到生成文件名,讀取,寫入等的部分運行時)。

因此,我有兩個問題:

  1. 是否有可能剖析Cython功能(與cdef定義)?如果是,如何?

  2. 如何使分析更具信息性(即測量每個被調用函數花費的時間)?

回答

0

Python和CPython的分析是確定性,這意味着它們通過捕捉牆時,在進入和退出功能工作,但只有功能探查已被告知個人資料。 他們不能給你一行一行的時間信息,除非他們也在每行代碼之前和/或之後記錄時間。

如果你不介意放棄測量精度(這不全是裂開了的話),那麼獲取逐行信息的一種方法是取少量堆棧樣本。每行代碼都包含時間(cumtime),佔總時間的一小部分,這正是它在堆棧上的時間的一小部分。所以當你拿一個堆棧樣本時,這個分數就是你會看到它的概率。如果您查看10或20個樣本,您會很清楚哪些代碼行需要很長時間。 Here's an example.

:)我有時會聽到的一個反對意見是:「不會完全減慢程序並使結果無效嗎?」好,考慮一下。有一行代碼,它需要幾分之一的時間,比如36.5%,所以它在堆棧上的時間很短。現在你啓動程序,9秒鐘後你打斷它看堆棧。該線路上有36.5%的機會。現在,門鈴響了,直到一週後你纔回過頭去看。這個長達一個星期的延遲是否會改變該行在堆棧樣本上的概率? 當然不是。 電腦耐心等待。無論您花多長時間觀察它,堆棧示例都不會更改。