代码执行时间:如何正确干燥多个timeit执行?

时间:2016-12-06 23:59:48

标签: python python-3.x dry timeit

我们假设我们希望使用timeit进行一些不同输入的性能测试。

显而易见的非DRY方式是这样的:

import timeit

# define functions to test
def some_list_operation_A(lst):
    ...

def some_list_operation_B(lst):
    ...

# create different lists (different input) to test the functions with
...
inputs = [lsta, lstb, lstc, ...]

# measure performance with first function
num = 10
t_lsta = timeit.timeit("some_list_operation_A(lsta)",
                        setup="from __main__ import some_list_operation_A, lsta",
                        number=num)
t_lstb = timeit.timeit("some_list_operation_A(lstb)",
                        setup="from __main__ import some_list_operation_A, lstb",
                        number=num)
t_lstc = timeit.timeit("some_list_operation_A(lstc)",
                        setup="from __main__ import some_list_operation_A, lstc",
                        number=num)
...

# print results & do some comparison stuff
for res in [t_lsta, t_lstb, t_lstc, ...]:
    print("{:.4f}s".format(res))
    ...

# do this ALL OVER AGAIN for 'some_list_operation_B'
...

# print new results

# do this ALL OVER AGAIN for 'some_list_operation_C'
# ...I guess you'll got the point
...

我认为应该非常清楚,这对于衡量不同输入的不同功能的性能是一种非常难看的方式。

我目前的做法是这样的:

...
inputs = dict()
inputs["lsta"] = lsta
inputs["lstb"] = lstb
inputs["lstc"] = lstc

for f in ["some_list_operation_A", "some_list_operation_B", ...]:
    r = dict()  # results
    for key, val in inputs.iteritems():
        r[key] = timeit.timeit("{}(inputs[{}])".format(f, key),
                                setup="from __main__ import {}, inputs".format(f),
                                number=num

    # evaluate results 'r' for function 'f' here
    # (includes a comparison of the results -
    #  that's why I save them in 'r')
    ...

    # loop moves on to next function 'f'

基本上,我在这里使用.format来插入函数名称并插入正确的数据inputs[key]。在.format填写所有{}后,结果是stmt一个正确的timeit字符串。

虽然这比明显的非DRY解决方案要短得多,但它的可读性也更低,更像黑客,不是吗?

对于此类问题,什么是合适的DRY解决方案?

我还想过用装饰器来简单地计算功能(这会很整洁?!) - 但我没有成功:装饰者不应该只打印结果。在我的# evaluate results 'r'步骤中,我不仅打印结果,而且还在比较它们:比如计算相对差异和内容。因此,我需要装饰器返回一些东西,以便比较每次运行的结果......

有人可以向我提出正确的方向,以获得干净的pythonic解决方案吗?我希望有更多漂亮/意识形态的代码......尤其是:更短代码!

0 个答案:

没有答案