PyPyでOok!を実装してみた。

こんにちはid:rokujyouhitoma@PyPy闇の軍団で、総裁とか団長とか総統と呼ばれています。です。


先日、職場で@mizuno_takaakiとBrainf*ckの話してたら、"Brainf*ckに似たオラウータンの鳴き声を元にしたOok!(ウーク)というのがあってだなー"と教わりました。

最後のPySpaに来て時間はあるし、良い機会なのでPurePythonとPyPy動的言語を生成するフレームワークRPythonToolchainJITあり・なし、最適化ありのそれぞれを実装して、実行速度を比較しようと思います。最速のOok!を目指す!!

RPythonToolchainはコンパイル時にオレオレ実装にJITを内蔵することができて嬉しいです。

基本、PyPyチュートリアルにあるBFのサンプルと全く一緒です。


ソースはこちら bitbucket.org rokujyouhitoma / lang-ook

環境

環境は下記の通り。

Ook!

samples/helloworld.ook

Ook!のHelloworldはこれ。
BrainF*ckのHelloworldするスクリプト書いて作成した。

"Hello, World!"を標準出力する。

Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook? Ook. Ook. Ook! Ook.
samples/bench.ook

"ZYXWVUTSRQPONMLKJIHGFEDCBA"を一文字づつ標準出力する。

Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook? Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook? Ook. Ook. Ook? Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook. Ook! Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook? Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook.
samples/mandel.ook

マンデルブロ集合を表示するコード。

(とてつなく長いのでコードは省略。

事前準備

ook!の処理系コードを落としてくる。

$ hg clone ssh://hg@bitbucket.org/rokujyouhitoma/lang-ook

以下は、PurePython、RPythonToolchainでJITあり、なし、JITの最適化ありによるHelloworld。

Pure PythonによるOok!
$ cd lang-ook
$ python ook.py samples/helloworld.ook
Hello, World!
PyPyのRPythonToolchainを使ったOok!(JITなし)

PyPyに付属してるtranlate.pyを活用する。

$ cd lang-ook
$ python ${PYPY_REPOSITORY_ROOT}/pypy/translator/goal/translate.py ook.py
$ ./ook-c samples/hello.ook
Hello, World!
PyPyのRPythonToolchainを使ったOok!(JITあり)

一応JITなしのook.pyファイルとは別にJITあり用のook-jit.pyを用意しとく。

$ python ${PYPY_REPOSITORY_ROOT}/pypy/translator/goal/translate.py --opt=jit ook-jit.py
$ ./ook-jit-c samples/hello.ook
Hello, World!
PyPyのRPythonToolchainを使ったOok!(JITあり、pypy.rlib.jit.purefunction最適化あり)
$ python ${PYPY_REPOSITORY_ROOT}/pypy/translator/goal/translate.py --opt=jit ook-jit2.py
$ ./ook-jit2-c samples/hello.ook
Hello, World!

比較まとめ

比較結果のまとめを先に紹介。

- PurePython JITなし JITあり JITあり、pypy.rlib.jit.purefunction最適化あり
bench.ook 66.56s(x1.0) 19.20s(x0.284) 3.02s(x0.045) 1.36s(x0.020)
mandle.ook 508.87s(x1.0) 114.23s(0.224) 15.86s(0.031) 7.18s(x0.014)

PurePythonよりJITありで最適化すると1 /0.014 = 71.4倍速くなった!

比較結果(bench.ook)

samples/bench.ookを使って比較する。

Pure PythonによるOok!
$ time python ook.py samples/bench.ook > /dev/null
python ook.py samples/bench.ook > /dev/null  66.56s user 0.08s system 99% cpu 1:06.72 total
PyPyのRPythonToolchainを使ったOok!(JITなし)
$  time ./ook-c samples/bench.ook > /dev/null
./ook-c samples/bench.ook > /dev/null  19.20s user 0.02s system 99% cpu 19.249 total
PyPyのRPythonToolchainを使ったOok!(JITあり)
$ time ./ook-jit-c samples/bench.ook > /dev/null
./ook-jit-c samples/bench.ook > /dev/null  3.02s user 0.01s system 99% cpu 3.034 total
PyPyのRPythonToolchainを使ったOok!(JITあり、pypy.rlib.jit.purefunction最適化あり)
$ time ./ook-jit2-c samples/bench.ook > /dev/null
./ook-jit2-c samples/bench.ook > /dev/null  1.36s user 0.00s system 99% cpu 1.371 total

比較結果(mandel.ook)

PythonによるOok!
$ time python ook.py samples/mandel.ook > /dev/null
python ook.py samples/mandel.ook > /dev/null  508.87s user 0.68s system 99% cpu 8:30.17 total
PyPyのRPythonToolchainを使ったOok!(JITなし)
$ time ./ook-c samples/mandel.ook > /dev/null
./ook-c samples/mandel.ook > /dev/null  114.23s user 0.12s system 99% cpu 1:54.45 total
PyPyのRPythonToolchainを使ったOok!(JITあり)
$ time ./ook-jit-c samples/mandel.ook > /dev/null
./ook-jit-c samples/mandel.ook > /dev/null  15.86s user 0.06s system 99% cpu 15.949 total
PyPyのRPythonToolchainを使ったOok!(JITあり、pypy.rlib.jit.purefunction最適化あり)
$ time ./ook-jit2-c samples/mandel.ook > /dev/null 
./ook-jit2-c samples/mandel.ook > /dev/null  7.18s user 0.04s system 99% cpu 7.220 total

まとめ

ということで、かなり簡単に実装することができました。RPythonToolchain恐るべし。