2017-07-11 45 views
7

列表使用无因的算法我想实现利用指数1..n因为它是非常容易出错的一个各项指标转变,我决定让智能和插入哑元每个列表的开始,所以我可以使用纸上的原始公式。PyPy:严重的性能下降时,与整数

对于急促的缘故,认为这个玩具例子:

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是否使用与否。

所以我的问题是双重的:

  1. 显然使用None是不是一个好主意,但是为什么呢?
  2. 是否有可能获得None的安全方法并保持性能?

编辑:由于阿明解释,并非所有的名单都是平等的,我们可以看到,它的策略是通过使用:

import __pypy__ 
print __pypy__.strategy(nums) 

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

回答

4

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

这也许可以固定内PyPy允许无作为特殊情况......

+0

这在某种程度上可以看到明确的,无论是优化或使用该名单的非优化的版本? – ead

+0

是的,''__pypy __。策略(LST)''。 –