Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl

SPVMの開発の今後の道のり - 仕様作成からJITによる最適化まで

Perlの処理を30倍速くすることを目標に開発しているSPVMですが、今後の道のりをここに記しておきます。

デバッグモード追加

現状は例外が起こったときに、コールスタックは表示されるけど、行番号とファイルは表示されない。これは、開発のときはちょっと不便なので、デバッグモードを追加する予定。

ウィークリファレンスの実装

Perlと同じように、SPVMのGCはリファレンスカウントで実装されている。現在制限として、オブジェクトの循環参照は禁止されているが、ウィークリファレンスを実装して、この制限を解きたい。

タグポインタという仕組みを使って、実装しようと思うのだが、まだ構想段階で、パフォーマンスを悪くすることなく、実装できるかは未知数。なんとかなりそうな気もする。

ネイティブインターフェース

JavaにはJNIというC言語に接続するためのインターフェースがあるのだけれど、これをSPVMでも作成する。このインターフェースがあれば、SPVMの配列などのデータ構造にC言語レベルでアクセスできる。

GPUやSIMDなどの並列処理を、記述したいときは、このネイティブインターフェースを使って実装できるようにする。

ダイナミックリンクライブラリ

ダイナミックリンクライブラリの機能を追加する。ダイナミックリンクライブラリが読み込めるようになると、必要に応じてC言語のライブラリが読み込めるようになる。

ダイナミックリンクライブラリが読み書きできるようになると、ネイティブインターフェースを使って書いたSPVMのライブラリを、CPAN上にアップして再利用できるようになる。

PerlのもっているXSやDynaLoaderの機能を使ってうまく実装できるような気もしている。

定数畳み込み

1 + 3 のようなものをコンパイル時に4にするような最適化を定数畳み込みという。これを実装する。

インライン展開

小さな関数を展開して、関数呼び出しをなくすインライン展開の機能

抽象構文木をSSA形式にして最適化

SSA形式というのは、「結果、演算子、値1、(値2)」という線形の形式で表現されたプログラムのことで、変数名がかぶらないように採番されるのが特徴のようだ。

SSA形式に変換すると、定数伝播や不要な式の削除が行いやすくなるらしい。

ループ最適化

ループの中で、undefのチェックや配列の範囲チェックしている部分を、外に追い出す。これによって命令数を少なくする。これは、かなり難しそうだ。

レジスタ型VM

現在はスタック型のVMとして実装している。でも、僕が調査したことによると、現在のCPUにおいては、コードサイズが小さいことよりも、命令数が少ないということが、パフォーマンスにとって重要らしい。

レジスタ型VMは命令長が長くなる代わりに、加算や減算などの命令数を減らすことができる。

またレジスタ型VMにすると、JITを行う場合に、ちょうどCPUの命令に近いような表現ができる。

VMを書き直すのはかなり大変そう。

機械語に対応するバイトコード生成

レジスタAにレジスタBを加算するというような、機械語に対応するバイトコードを作成する。これによって、定数決め打ちで演算ができるので、速くなる。また、JITにちょうど対応する命令を生成できる。

JIT

最後にJIT。つまり実行時コンパイル。僕は、どうしてJITにすると速くなるのかという疑問を持っていた、だってVMだって結局は機械語で実行されているのにねって。

JITを行うと速くなる理由は、命令のジャンプがなくなるということに尽きる。

バイトコード命令の場合は、命令を実行するために、その命令の位置までジャンプしないといけない。このジャンプの負荷が大きい。

JITを行うと機械語命令を、連続した領域に並べることができる。これでジャンプがなくなり、速くなるというわけ。

「次期PHPにJITがやってきそうでうらやましそう」といっていた方がいましたけど、Perlにもやってきますよ!

地道に順番に実装してく

これを地道に順番に実装していく。SPVMは、Javaとgperlとluajit2が、大きな参考になっている。

Perlの可能性が広がって、ますますPerlが面白く、いろんな分野にチャレンジできると思う。30代の目標は、ひたすらオープンソースで開発して、インフラを作ること。40代の目標は、教育、研究、出版という分野で、Perlを横に広げることだ。今はそういう目標を持っている。

Giblog