Python速度测试——为什么一个异常故障要花费这么多时间
对于“尝试从列表中删除x”的简单操作,我假设“尝试/例外”工作流比“如果/然后”工作流要快。在下面的示例中,except失败(x不在列表中)花费的时间比权限请求(如果x在列表中)多,即使出现异常的可能性为16.6%。为什么? 以下是我编写的测试及其结果:Python速度测试——为什么一个异常故障要花费这么多时间,python,Python,对于“尝试从列表中删除x”的简单操作,我假设“尝试/例外”工作流比“如果/然后”工作流要快。在下面的示例中,except失败(x不在列表中)花费的时间比权限请求(如果x在列表中)多,即使出现异常的可能性为16.6%。为什么? 以下是我编写的测试及其结果: import random, time, timeit class Timer(object): def __enter__(self): self.start = time.time() return
import random, time, timeit
class Timer(object):
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
self.end = time.time()
self.secs = self.end - self.start
self.msecs = self.secs * 1000 # millisecs
def a_function():
a_list = list(xrange(10))
choice_list = list(xrange(12))
choice = random.choice(choice_list)
try:
a_list.remove(choice)
except ValueError:
pass
def b_function():
a_list = list(xrange(10))
choice_list = list(xrange(12))
choice = random.choice(choice_list)
if choice in a_list:
a_list.remove(choice)
with Timer() as a:
print('test_a', timeit.timeit("a_function()", number=10000, setup="from __main__ import a_function"))
with Timer() as b:
print('test_b', timeit.timeit("b_function()", number=10000, setup="from __main__ import b_function"))
结果是:
1次尝试:('test_a',0.029724836349487305)('test_b',0.0270681381225594)
2次尝试:('test_a',0.02960801124572754)('test_b',0.026785850524902344)
3次尝试:('test_a',0.0296549705810547)('test_b',0.02665996551513672)
此外,如果我将choice_列表范围增加到20,则差异会扩大,因为异常会更频繁地发生。如果python强烈要求宽恕而不是许可,为什么失败似乎要花费大量时间?异常在任何语言中都非常昂贵,这是对它们的滥用 异常是指代码无法解释并且在正常操作过程中不会出现的异常情况。不同的语言对什么是例外有不同的规则,但是16%的时间发生的事情不是例外,只是不寻常
异常代价高昂,因为它们涉及堆栈展开和跳转、暂停正常处理以及搜索处理程序。If/then是一个标准的、正常的、有效且清晰的条件 异常在任何语言中都非常昂贵,这是对它们的滥用 异常是指代码无法解释并且在正常操作过程中不会出现的异常情况。不同的语言对什么是例外有不同的规则,但是16%的时间发生的事情不是例外,只是不寻常
异常代价高昂,因为它们涉及堆栈展开和跳转、暂停正常处理以及搜索处理程序。If/then是一个标准的、正常的、有效且清晰的条件 这完全是瞎猜,但可能是因为异常处理基于类,而if/then则纯粹基于逻辑。因此,解释器可以优化简单的条件处理,而不是类流
这是一个彻头彻尾的秘密,但可能是由于异常处理是基于类的,而if/then是纯粹基于逻辑的。因此,解释器可以优化简单的条件处理,而不是类流
Try/catch-by-demancess必须包含与if/then相同的构造(条件跳转)。因为它必须处理更多的事情(比如返回错误),try/catch必然比您自己做测试慢。那
Timer
context manager做什么?这似乎是死代码,而你已经在起诉timeit
。@delnan计时器可能是我第一次启动速度测试代码时的问题。我通常只需编写函数。Try/catch必须包含与if/then相同的构造(条件跳转)。因为它必须处理更多的事情(比如返回错误),try/catch必然比您自己做测试慢。那Timer
context manager做什么?这似乎是死代码,而你已经在起诉timeit
。@delnan计时器可能是我第一次启动速度测试代码时的问题。我通常所做的只是编写函数。虽然我原则上同意您的意见,但在Python中,强烈鼓励用户使用try…除了在许多情况下使用if…then
构造之外,其他语言都会使用if…then子句。虽然计算效率不高,但使用异常向调用堆栈上传递某些类型的消息在语义上是有效的(在Python中)。这一点尤其正确,因为Python中鼓励使用“duck-typing”范式。@JoelCornett:有趣。我对Python知之甚少(我是一个喜欢Ruby的人)。在Ruby中,我们有一个特殊的异常结构,它实际上被命名为throw和catch。例外是为真正例外的人保留的(另一个例子是Obj-C)。显然,OP对效率感兴趣,另外,try…除了在OP的示例中,似乎对代码的语义没有任何有用的贡献。@doctorlove:这很有趣。谢谢虽然我原则上同意您的看法,但在Python中,强烈鼓励用户使用try…但在许多情况下,其他语言会使用if…then
子句。虽然计算效率不高,但使用异常向调用堆栈上传递某些类型的消息在语义上是有效的(在Python中)。这一点尤其正确,因为Python中鼓励使用“duck-typing”范式。@JoelCornett:有趣。我对Python知之甚少(我是一个喜欢Ruby的人)。在Ruby中,我们有一个特殊的异常结构,它实际上被命名为throw和catch。例外是为真正例外的人保留的(另一个例子是Obj-C)。显然,OP对效率感兴趣,另外,try…除了在OP的示例中,似乎对代码的语义没有任何有用的贡献。@doctorlove:这很有趣。谢谢CPython不进行此类优化。CPython不进行此类优化。