2015-11-09 63 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%的机会。现在,门铃响了,直到一周后你才回过头去看。这个长达一个星期的延迟是否会改变该行在堆栈样本上的概率? 当然不是。 电脑耐心等待。无论您花多长时间观察它,堆栈示例都不会更改。