PyPy:在整数列表中使用None时性能会受到严重影响

因为我想要实现的算法使用索引1..n并且由于很容易将每个索引移动一位,所以我决定变得聪明,并在每个列表的开头插入一个虚拟元素,这样我就可以使用原始公式该文件。

为了简洁起见,请考虑这个玩具的例子:

def calc(N):
    nums=[0]+range(1,N+1)
    return sum(nums[1:]) #skip first element

然而,我担心,我的结果是虚假的,因为我可以在某处意外地访问第0个元素,而不会意识到这一点。 所以我变得更聪明,并且使用None而不是0作为第一个元素 - 每一个使用它的算术运算都会导致运行时错误:

def calc_safe(N):
    nums=[None]+range(1,N+1) #here we use "None"
    return sum(nums[1:]) 

令人惊讶的是,这个小小的改变导致了pypy的巨大性能损失(即使是现在的5.8版本) - 代码变得慢了大约10倍! 以下是我的机器上的时间:

                    pypy-5.8    cpython
calc(10**8)         0.5 sec     5.5 sec
calc_safe(10**8)    7.5 sec     5.5 sec

作为侧节点:CPython的不关心,是否None使用或不使用。

所以我的问题是双重的:

  • 显然使用None不是一个好主意,但为什么?
  • 是否有可能获得None方法的安全并保持性能?
  • 编辑:正如Armin所解释的,并非所有的列表都是平等的,我们可以看到,通过以下方式使用了哪种策略:

    import __pypy__ 
    print __pypy__.strategy(nums)
    

    在第一种情况下,它是IntegerListStrategy和第二个ObjectListStrategy 。 如果我们使用大整数值(如2**100 )而不是None则会发生同样的情况。


    PyPy对于只包含整数的列表有一个特殊的例子---它将它们存储为一个array.array 。 如果其中有一个None,那么这个优化不再起作用。

    这可能会在PyPy中修复以允许None作为特殊情况...

    链接地址: http://www.djcxy.com/p/96633.html

    上一篇: PyPy: Severe performance penalty when using None in a list with integers

    下一篇: What is exports and prototype in Javascript?