为什么评估布尔对象需要花费时间在python中
作者:互联网
我使用timeit模块比较了这两个代码片段,并意识到第二个代码片段稍快一些:
~$python -m timeit —setup "l=[1, 2];k=1" "l[k==1]"
10000000 loops, best of 3: 0.0414 usec per loop
~$python -m timeit —setup "l=[1, 2];k=1" "l[0 if k==1 else 1]"
10000000 loops, best of 3: 0.0372 usec per loop
由于逻辑是相同的,我认为评估布尔对象比整数等价花费更多的时间(True == 1和False == 0),因此我提出了以下基准测试,结果证明我是正确的:
~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0411 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0394 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0416 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0428 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0394 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0393 usec per loop
~$
~$
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop
但我不知道其根本原因是什么.我的意思是为什么评估True和False需要更多时间?在基准测试中我也发现了另一个神秘的事情.在基准测试的第一部分中,结果存在差异,而第二部分的数字是稳定的.
解决方法:
对于l [k == 1]和l [0如果k == 1其他1],你没有足够长的时间.你看到的差异在于你从随机变化中获得的差异.我不确定哪种形式最终更快,但更长的试验显示出相反的效果:
>>> timeit.timeit('l[k==1]', 'l=[1,2];k=1', number=100000000)
10.782931089401245
>>> timeit.timeit('l[0 if k==1 else 1]', 'l=[1,2];k=1', number=100000000)
11.140317916870117
l [0如果k == 1其他1]出乎意料地竞争,因为l [k == 1]没有达到BINARY_SUBSCR操作码的fast path:
TARGET_NOARG(BINARY_SUBSCR)
{
w = POP();
v = TOP();
if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: list[int] */
Py_ssize_t i = PyInt_AsSsize_t(w);
if (i < 0)
i += PyList_GET_SIZE(v);
if (i >= 0 && i < PyList_GET_SIZE(v)) {
x = PyList_GET_ITEM(v, i);
Py_INCREF(x);
}
else
goto slow_get;
}
else
slow_get:
x = PyObject_GetItem(v, w);
在你的第二个测试中,还有另一个因素,在Python 2中,True是内置变量查找,而1是更快的LOAD_CONST. LOAD_CONST仅索引到代码对象的co_consts元组中,而内置查找则需要两次dict查找.
标签:python,boolean,internals,performance 来源: https://codeday.me/bug/20190628/1312820.html