4半世紀前に「BASICコンパイラ」に憧れた皆様こんにちは。
当時、インタプリタとコンパイラは格が違う存在だった。
・ホビイストはインタプリタ、プロはコンパイラ
・無料でパソコンについてくるのがインタプリタ、何万円も出して買うのがコンパイラ
・起動してすぐに使えるのがインタプリタ、段取りが多くて敷居が高いのがコンパイラ
そしてなにより、
・遅いのがインタプリタ、速いのがコンパイラ
パソコン雑誌の広告等で「コンパイラ」を見て憧れを募らせていた私は、Javaや.NETのJITコンパイラに騙されているような気が今でも少しする。インタプリタなのかコンパイラなのかどっちなんだ、と詰め寄りたくなる。
もちろん、(昔の)インタプリタと(昔の)コンパイラのどちらと比較しても優れているのがJITコンパイラだということは知っている。それでも、あの絶対的な格の違い、越えられない壁はいったいどうなってしまったんだ、という気持ちにかられる。
そして今度は、インタプリタがJITコンパイラになるという。
PyPy を使ってインタプリタを書く
これを見て私の脳内には、BASICインタプリタに魔法をかけるとBASICコンパイラに変身する、という夢のような光景が展開された。ちなみにPythonではベンチマークが3倍速になるという。
(といっても既存のコードがそのまま3倍速になるわけではない。多くのソフトウェアはI/Oのために内部表現と外部表現を変換するところがボトルネックになっており(JavaのJNIが遅いのはこれ。「速度が必要なところはCで書けば~」という議論が成り立たない最大の理由)、PyPyはその変換に余計な手間がかかるので、I/Oの多いソフトウェアではかえって遅くなる)
格や夢のことはさておき現実問題としては、メリットは速度だけなので、実のところほとんどどうでもいい。が、「書きやすさ」や「開発のしやすさ」と違って速度は定量的に比較できるので、比較してみたくなる。こう書くとまるで経済学者と街灯の話だが、まさにそのものだ。
「Pythonでは3倍速」といっても、比較対象は別に速度自慢でもないPythonにすぎない。相手がJava VMではどうか。では試してみるか、と思って、上にリンクした紹介を真に受けた私はJava VMのサブセット(マイクロベンチマークが取れる程度のもの)を書こうとして、クラスファイルのパーサを書いたところで心が折れた。
PyPyでインタプリタを書くのに使う言語はRPythonといい、Pythonのサブセットということになっている。……と書くと、書きやすい言語のように聞こえるかもしれない。上の紹介でも「これらはそれほど難しくはありませんよね?」などと愛想のいいことが書いてある。
真っ赤な嘘だ。
RPythonは、
・型に厳密
ひとつのリストや辞書には同じ型のオブジェクトしか入れられない。しかし型を宣言しないPythonでどうやって型に厳密にするのかというと、
・型を推論し、暗黙の型宣言をつける
C#のvarのような型推論なら便利なものだが、暗黙の型宣言となるとあまり穏やかでない。とはいえ、これだけならまだ大した問題ではないが、
・ジェネリックプログラミングができない
なにしろPythonは型の緩い言語なので、テンプレートも総称型もない。すべてのメソッドには唯一の暗黙の厳密な型宣言をつけられるように書かなければならず、そのため同じ中身のメソッドを引数の型ごとに書かなければならない。重要な組み込み関数でも、唯一の暗黙の型宣言がつけられないものは削られている。たとえばmap()は削られている。
ここまでならまだ乗り越えられない壁でもない。が、この上さらに、
・Hello, worldのコンパイルに60秒かかる
「コンパイルしない方法もあってそれだともっと早くできる」という情報もあるが、型チェックが手薄なのかどうかで役に立たなかった。
疑問――なぜPyPyの作者はRPythonなどという世にも使いにくい言語を作る必要があったのか?
魔法の都合上、型に厳密な言語が必要なのはわかる。が、それならML系の言語ではなぜいけなかったのか。まるで見当がつかない。
もし、最初から型に厳密な言語として設計された既存の言語でインタプリタを書けるようになったら、JITコンパイラの恩恵も世に広まるだろう。それまでは無理だ。
一応そのパーサを載せておく。RPythonの恐怖をまだ知らない向きは、私の遺志を継いで、Java VM(のベンチマーク用サブセット)に挑戦されたい。