我想知道Deferred执行的时间长短,从第一个回调函数被触发到最终结果。有没有什么方法可以做到这一点,可能是以非侵入方式(即不修改任何回调函数以跟踪执行时间)?
如果您正在使用“twistd”运行程序,则可以使用选项“--profile”来帮助您对扭曲代码进行分析。
twistd "other options" --profile=statsfile --profiler=cProfile --savestats
要查看统计数据:
import pstats
stats = pstats.Stats('statsfile')
stats.sort_stats('time').print_stats()
回调函数在延迟对象被触发后立即执行。但是“立即”指的是延迟链中的每个回调都必须被执行,并且它们会有自己的执行时间。此外,包括反应器循环在内的各种代码片段也将有它们自己的执行时间。
因此,“立即”一词意味着尽快执行。
考虑以下糟糕的示例:
from twisted.internet import reactor, defer
import time
def timeit(func):
def wrapper(*arg):
t1 = time.time()
res = func(*arg)
t2 = time.time()
print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
return res
return wrapper
d = defer.Deferred()
@timeit
def callfunc1(result):
print 'XXXXX'
@timeit
def callfunc2(result):
print 'YYYYY'
d.addCallback(callfunc1)
d.addCallback(callfunc2)
t1 = time.time()
d.callback(True)
t2 = time.time()
print '%0.3f ms' % ((t2-t1)*1000.0)
输出:
XXXXX
callfunc1 took 0.039 ms
YYYYY
callfunc2 took 0.005 ms
0.108 ms
如果您想优化应用性能,请按照以下步骤操作:
安装此工具
运行您的twisted应用并收集原始数据:
twistd --savestats -n --profile=myapp.hotshot myapp
然后将'hotshot'转换为'calltree':
hotshot2cg myapp.hotshot > myapp.calltree
现在可以使用Kcachegrind工具查看调用树。
kcachegrind myapp.calltree
使用此工具,您可以查看twisted事件循环的调用图和百分比执行时间。所以无需修改代码,只需运行此工具即可。
P.S. 检查内存使用情况:
性能分析对于我想要实现的目标来说有点过头了。
最终我找到了一个解决方案,它不需要对现有代码进行大量修改,但并不是“通用”的:
我的原始代码大致如下:
def myfunc(*args):
d = Deferred()
d.addCallback(cb1)
...
d.addCallback(lambda x: MyObject(x))
我现在有:
def myfunc(*args):
init_time = time.time()
d = Deferred()
d.addCallback(cb1)
...
d.addCallback(lambda x: MyObject(x, init_time))
class MyObject:
def __init__(self, *args):
...
self.exec_time = time.time() - init_time
它做了我想要的事情,但我希望 Deferred 结构会暴露一些跟踪执行时间本身的东西,而不是必须调整我的对象。从源代码中,我看不到有这样的东西可用:http://twistedmatrix.com/trac/browser/tags/releases/twisted-10.0.0/twisted/internet/defer.py#L137