我想从对象的角度来描述python代码。 E.g:
foo = Foo()
profiled_foo = add_profiling(foo)
# use profiled_foo like foo
...
# later
profiled_foo.print_profile()
我想获得每种方法的调用以及每种方法花费的累计时间。我没有发现任何类似的东西,虽然我认为写起来不应该太难。
这样的库是否存在?或者也许不是因为这种方式分析会是一个坏主意?
根据Paul McGuire的回答:
import inspect
from time import sleep
from profilehooks import profile
class Foo(object):
def a(self):
sleep(0.1)
def b(self):
sleep(0.3)
def c(self):
sleep(0.5)
def add_profiling(obj):
for k in dir(obj):
attr = getattr(obj, k)
if inspect.ismethod(attr) and k != '__init__':
setattr(obj, k, profile(attr))
if __name__ == '__main__':
foo = Foo()
add_profiling(foo)
foo.a()
foo.a()
foo.b()
foo.b()
foo.a()
foo.c()
*** PROFILER RESULTS ***
c (oprof.py:13)
function called 1 times
3 function calls in 0.501 CPU seconds
Ordered by: cumulative time, internal time, call count
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.501 0.501 oprof.py:13(c)
1 0.501 0.501 0.501 0.501 {time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
0 0.000 0.000 profile:0(profiler)
...
答案 0 :(得分:6)
我在这些装饰器上取得了相当不错的成功:http://mg.pov.lt/profilehooks/
答案 1 :(得分:1)
您可以查看http://docs.python.org/library/profile.html
在我个人看来,cProfile是python的更直观,更快速的分析工具。
要分析单个类,您可以编写简单的测试脚本并使用cProfile运行它们。
答案 2 :(得分:1)
您之前可能已经听说过这一点,但是为了自己的缘故和分析之间存在区别,目的是尽可能快地运行代码。
你想要对方法的所有调用求和的每个方法的累积时间是好的,因为如果你将它除以总执行时间,你得到方法负责的时间百分比。 如果有一些东西可以修复以获得更好的速度,那么它就属于自己代码中的高百分比方法。
比获得高累积百分比的方法更好的是获得高累积百分比的代码行。 那是因为如果你想查看问题所在的方法,那么你正在寻找具有高百分比的特定代码行。 因此,如果您的探查器告诉您这些线的位置,您已经(取决于方法大小)可能比定位问题的精度高一个数量级。
比知道具有高百分比的代码行的位置更好的是知道它们可能被执行的上下文。
有些人认为有必要进行准确的时间测量。 但是,一旦你在你的代码中找到一条明确代表获得良好加速的机会的行,因为删除 - 替换 - 以不同方式执行它将节省相当大的总时间百分比,如果你对该百分比的估计是关闭的,那真的很重要吗一点? 假设您找到该行并且您认为它的成本为50%。 如果修复它真正的实际节省量只有30%或者高达70%,你会花时间去解决这个问题吗?
这就是我鼓励堆叠采样的原因,this is a small example。
堆栈样本会自动为您提供行级百分比,因为行的百分比成本只是包含它的样本的百分比。 它们会自动包含阻塞时间,例如I / O,这是您需要知道的,因为它有助于整体时间。 如果采集100或1000个样本,您可以获得高精度的测量,但是一些非常简单的统计数据证明,对于除最小问题之外的所有问题,少量样本足以精确定位问题。 最后,在样本中说明一条线是否被充分利用的上下文。 许多分析器将样本混合在一起以获取数字,但不要让用户看到代表性的样本。 因此,他们倾向于认为“热”代码行是必要的,而事实上上下文可以告诉他们不是。