PyPyを速くする(2) 関数型 vs. 手続き型

Problem 1を考えます。ふつうに書くとこんな感じです。

N = 10 ** 8     # オリジナルは1000
print sum(n for n in xrange(1, N) if n % 3 == 0 or n % 5 == 0)

この問題はプログラマを関数型に導くためのものなのです。
これを動かすと、Pythonで13秒、PyPyで3.9秒でした。
これを露骨に手続き型で書くとこうなります。

N = 10 ** 8
s = 0L          # 0とするより少し速い
for n in xrange(1, N):
    if n % 3 == 0 or n % 5 == 0:
        s += n
print s

s = 0Lとしているのは、PyPyでは型が決まっていたほうが速いからです。
Pythonで17.5秒、PyPyで2.8秒でした。PyPyで速いのは予想できたのですが、Pythonでは逆に遅くなるんですね。
まとめると、

  Python PyPy
関数型 13秒 3.9秒
手続き型 17.5秒 2.8秒

【結論】
PyPyでは手続き型にすると速くなることがあります。あまり好ましくないですが、ここがクリティカルだという場合は手続き型にするのも手です。