zoukankan      html  css  js  c++  java
  • 计算运行时间工具timeit

    timeit的功能和用法

    timeit 模块提供了测试一小段代码运行时间的功能。我前面有一篇文章用它来测试定义 __slots__ 对对象访问速度的提升情况,参见这里
    官方文档 上有下面这样的使用例子:

    # 从命令行调用
    python -m timeit '"-".join([str(n) for n in range(100)])'
    
    # 从REPL调用
    >>> import timeit
    >>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
    0.7288308143615723
    

    使用 timeit 的时候可以直接调用其定义好的 timeit.timeit , timeit.repeat , timeit.default_timer 方法,或者定义一个类 timeit.Timer ,使用本身的方法。

    # API
    
    timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
    
    timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
    
    class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>)¶
    
    • timeit() 接受的第一个参数stmt为要计算时间的表达式,第二个参数setup为初始化的表达式。
    • timer参数为计时器,在不同平台默认不一样,参照这里 ,但不管是Unix还是Windows测得的时间都是系统经过的时间,所以是有可能被正在运行的其它程序影响的。
    • number参数是表达式执行的次数,所以这里返回的时间是执行1000000次总和的时间。
    • timeit.repeat() 中的repeat参数是测试重复执行的次数,相当于调用number次的timeit(),number默认为3,返回3次运行时间的列表,通常可以取min()来评估程序的执行时间。
    • timeit.repeat() 中除了最小值其他的值得参考意义可能不大,因为有可能是受到系统中其它程序影响导致的
    • 注意python版本不同导致的接口参数不同,这里默认采用python2.7版本

    接下来看一些复杂点的示例

    # 多行表达式的调用
    >>> import timeit
    >>> attribute is missing
    >>> s = """
    ... try:
    ...     str.__nonzero__
    ... except AttributeError:
    ...     pass
    ... """
    >>> timeit.timeit(stmt=s, number=100000)
    0.9138244460009446
    
    
    # 测试函数调用时间
    def test():
        """Stupid test function"""
        L = []
        for i in range(100):
            L.append(i)
    
    if __name__ == '__main__':
        import timeit
        print(timeit.timeit("test()", setup="from __main__ import test"))
    

    其它

    当我在网上浏览timeit相关资源时看到了这篇文章, 上面提到了通过上下文管理器(context manager)实现一个计时器,利用了变量的生命周期相关特性(#TODO),虽然就像作者所说,可以加上其它的特性比如循环次数等以及更优雅的实现一个计时器,代码如下,可供参考:

    # Source code: https://gist.github.com/pengmeng/78a25663c20ab8890b81
    __author__ = 'mengpeng'
    import time
    
    
    class timeme(object):
        __unitfactor = {'s': 1,
                        'ms': 1000,
                        'us': 1000000}
    
        def __init__(self, unit='s', precision=4):
            self.start = None
            self.end = None
            self.total = 0
            self.unit = unit
            self.precision = precision
    
        def __enter__(self):
            if self.unit not in timeme.__unitfactor:
                raise KeyError('Unsupported time unit.')
            self.start = time.time()
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.end = time.time()
            self.total = (self.end - self.start) * timeme.__unitfactor[self.unit]
            self.total = round(self.total, self.precision)
    
        def __str__(self):
            return 'Running time is {0}{1}'.format(self.total, self.unit)
    

    运行示例:

    from timeme import timeme
    with timeme('ms', 6) as t:
        result = sum(range(100000))
    
    print(t) # Running time is 5.2948ms
    print(t.total) # 5.2948
    

    参考资料

  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/nisen/p/6045182.html
Copyright © 2011-2022 走看看