PyPyのStringBuilderの処理速度を試す

PyPy Status BlogのエントリでPyPyにStringBuilderという高速でmutableな文字列がある事を知り、処理速度をためしてみました。

StringBuilderはやい。

#!/usr/bin/env pypy
from random import choice
from string import ascii_letters as ls
import time
import StringIO
try:
    import __pypy__
except:
    pass


ls = unicode(ls)
ch = lambda: choice(ls)

def measure(fn):
    # msec
    s = time.time()
    fn()
    e = time.time()
    return (e-s) * 1000

it = 100000

def naive():
    s = u''
    for i in range(it):
        s += ch()
    return s

def join():
    lst = []
    for i in range(it):
        lst.append(ch())
    s = u''.join(lst)
    return s

def strio():
    ist = StringIO.StringIO()
    for i in range(it):
        ist.write(ch())
    return ist.getvalue()

def pypy():
    sb = __pypy__.builders.UnicodeBuilder(it)
    for i in range(it):
        sb.append(ch())
    return sb.build()

lst = []
for fn in [naive, join, strio] + ([pypy] if locals().get('__pypy__', False) else []):
    lst.append([fn.__name__, measure(fn)])
for name, sec in lst:
    print '%7s %8.2f %8.2f' % (name, sec, lst[0][1] / sec)

# $ uname -a
# Linux ******** 2.6.32-24-generic #43-Ubuntu SMP Thu Sep 16 14:58:24 UTC 2010 x86_64 GNU/Linux
# $ pypy -V
# Python 2.7.1 (d8ac7d23d3ec, Aug 17 2011, 11:51:19)
# [PyPy 1.6.0 with GCC 4.4.3]
# $ python -V
# Python 2.6.5
# $ python s.py
#   naive  5819.58     1.00
#    join   140.81    41.33
#   strio   338.93    17.17
# $ pypy s.py 
#   naive  9947.15     1.00
#    join    31.23   318.53
#   strio    51.92   191.59
#    pypy    16.39   606.75