准确测试Pypy和CPython性能

17

问题描述:

我有这个自定义的“校验和”函数:

NORMALIZER = 0x10000


def get_checksum(part1, part2, salt="trailing"):
    """Returns a checksum of two strings."""

    combined_string = part1 + part2 + " " + salt if part2 != "***" else part1
    ords = [ord(x) for x in combined_string]

    checksum = ords[0]  # initial value

    # TODO: document the logic behind the checksum calculations
    iterator = zip(ords[1:], ords)
    checksum += sum(x + 2 * y if counter % 2 else x * y
                    for counter, (x, y) in enumerate(iterator))
    checksum %= NORMALIZER

    return checksum

我希望测试一下Python3.6和PyPy的性能差异,看看这个函数在PyPy上表现是否更出色。但我不确定最可靠、最简洁的方法是什么。

我尝试过的和我的问题:

目前,我在两种情况下都使用timeit

$ python3.6 -mtimeit -s "from test import get_checksum" "get_checksum('test1' * 100000, 'test2' * 100000)"
10 loops, best of 3: 329 msec per loop

$ pypy -mtimeit -s "from test import get_checksum" "get_checksum('test1' * 100000, 'test2' * 100000)"
10 loops, best of 3: 104 msec per loop

我的担忧是我不确定timeit是否是用于在PyPy上完成任务的正确工具,因为可能存在JIT预热开销

此外,在报告测试结果之前,PyPy本身会报告以下内容:

WARNING: timeit is a very unreliable tool. use perf or something else for real measurements
pypy -m pip install perf
pypy -m perf timeit -s 'from test import get_checksum' "get_checksum('test1' * 1000000, 'test2' * 1000000)"

如何最好和最准确地测试相同的函数在这些以及其他可能的Python实现中的性能?


2
这个测试有实际作用吗?看起来你只是进行了安装设置,没有真正的测试命令? - MSeifert
@MSeifert啊,我真是个傻瓜,你说得完全正确。那里只有设置,我已经更新了答案,留下了问题的后半部分。谢谢! - alecxe
2个回答

3

2
并不完全清楚您想要测量什么。"性能"可以根据您的用例而有所不同。
  • 您是想衡量函数在一切都被热身(特别是JIT,但也包括库导入、文件加载等)后的原始速度吗?那么您可能需要像Haroldo_OK建议的那样进行大量重复--repeat。随着重复次数的增加,代码中其他部分花费的时间会逐渐变得“不重要”。
  • 您是为了学习还是为了实际应用而测量这些东西?如果是后者,最好在类似条件下测试您的代码(传递给函数的字符串长度、迭代次数、代码的热/冷调用等)。我的印象是使用Python接口而不是CLI会给您更多测量所需的灵活性。
值得注意的是,{{link1:timeit会关闭垃圾回收}},所以如果你正在寻找“真实世界”的测量结果,也许你想把它打开(请参阅链接了解如何操作)。
如果您试图提高速度,则使用像{{link2:cProfile}}这样的分析器可能有助于隔离您想要测量速度的代码。它支持Python3.6和{{link3:pypy}}。
我实际上没有回答你的问题,但希望这有所帮助 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接