关于定时类初始化的想法

时间:2013-11-21 11:40:28

标签: python performance

我有很多课程。其中一些初始化很慢,我想通过使用cached properties来延迟一些初始化。第一步是确定哪些是罪魁祸首。所以我想计算以下代码:

class MyClass:

    def __init__(self, ....):
        # start measurement
        ...
        # end measurement, report

我的要求是:

  • 计时结果为日志条目。
  • 尽可能少侵入
  • 我希望将其保留在我的代码中,但可以使用标记
  • 禁用它

所以我的第一个想法是实现一个通用的timeme函数:

def timeme(func):    
    def f(*args, **kwargs):
        start = # get start timestamp
        result = func(*args, **kwargs)
        end = # get end timestamp
        # report timespan
        return result
    return f

(可用于计算任何类型的函数,而不仅仅是类方法)

现在我可以做到:

class MyClass:

    @timeme
    def __init__(self, ....):
    ...

还有更多的 pythonic 方式吗?一些标准库支持这个?工具支持?这种方法有任何明显的缺点吗?

1 个答案:

答案 0 :(得分:0)

标准库中没有这样的内容,除了cProfile进行常规分析。

我建议您创建一个简单的元类,如果设置了某个全局/环境变量,它将包装__init__方法。这样,您就不需要使用调试/分析装饰器来混淆代码。

只是一个起点(尚未测试过):

import functools

# Python 3.3 for time.monotonic is required
import time

class TimedMeta(type):
    timing_enabled = True

    @classmethod
    def _wrap_timeit(mcls, cls_name, meth):
        @functools.wraps(meth)
        def wrapped(*args, **kwargs):
            start = time.monotonic()
            try:
                return meth(*args, **kwargs)
            finally:
                end = time.monotonic()
                mcls._record_timing(cls_name, end - start)

    @classmethod
    def _record_timing(mcls, cls_name, timing):
        raise NotImplementedError

    def __new__(mcls, name, bases, dct):
        if mcls.timing_enabled:
            try:
                init = dct['__init__']
            except KeyError:
                pass
            else:
                dct['__init__'] = mcls._wrap_timeit(name, init)

        return super().__new__(mcls, name, bases, dct)

class Timed(metaclass=TimingMeta):
    pass

class Foo(Timed):
    def __init__(self):
        time.sleep(1.0)