あけましておめでとうございます。このたび、gihyo.jpの新春特別企画として記事「PHP処理系の未来」を寄稿いたしました。HHVMとPHP7を絡めて最近のPHPの動向を紹介するような内容になっていますので、是非ご覧くださいませ。
この記事を書くにあたり、HHVM以外にも有望なPHP処理系があるかどうかを調べていました。その結果、HHVMほどではないにせよ実用レベルに近いPHP処理系が複数あることがわかりました。
そうした実装のうち、今回は.NET FrameworkおよびMono環境で動くPHPコンパイラPhalangerを紹介します。PhalangerはC#で書かれており、PHPソースコードから.NETアセンブリを出力します。Windows上では本家PHPより高速ということですし、PHPをVisualStudioで開発したり.NETの資産を利用したりする狙いもあるようで、夢が広がるプロジェクトですね。Phalanger開発者がDEVSENSE社という会社を起業して有償サポートを提供しているなど、本気度が高いPHP処理系の一つだと言えるでしょう。
ただ、中の人も含め常用している人は全員Windows環境のようで、Linux/MacOSXの情報は非常に少ない状況です。今回MacOSXのMono環境で動かせたので紹介します。
Monoのインストール
まずはMonoを準備してください。PhalangerではMonoの設定ファイルを書き換える必要があるので、普段使っているMonoとは別にインストールした方が無難かと思います。普段Monoを使っていない場合は単にHomebrewでインストールすれば良いでしょう。
$ brew install mono
Phalangerのインストール
PhalangerにはMacOSX用のパッケージはありません。Windows用のバイナリファイルをダウンロード&展開します。僕はPhalangerのダウンロードページから「Phalanger 3.0.0.4072 (bin).zip」をダウンロードしました。
これを作業ディレクトリに展開し、「Installation/3.0/Linux - PhalangerWiki」を参考に作ったインストールスクリプトでインストールします。インストールスクリプト内でxmlstarletを使っているので、必要に応じてインストールしてください。
$ mkdir /tmp/phalanger-setup $ cd /tmp/phalanger-setup $ unzip -x "$HOME/Downloads/Phalanger 3.0.0.4072 (bin).zip" $ brew install xmlstarlet $ curl -o phalanger_install_3.0.sh https://gist.githubusercontent.com/hnw/3d3b280bdd9b6a3835b8/raw/3068f3ef31d4a6b0ae88c455d526b790250f7ea3/phalanger_install_3.0.sh $ bash ./phalanger_install_3.0.sh
トラブったらスクリプトの中身を熟読してください。僕自身、Mono力が足りないため中身を全部把握しているわけではありません。
PHPプログラムのコンパイル&実行
Phalangerのコンパイラはphpc.exeです。下記のようにしてPHPプログラムをコンパイルします。
$ mono /usr/local/lib/phalanger/bin/phpc.exe /out:/tmp/ bench.php
これでコンパイル結果が/tmp/bench.exeに出力されます。/outオプション無しだとカレントディレクトリのbin/以下にバイナリを作るので注意してください。
できたexeファイルはやはりmonoで動かせます。
$ mono /tmp/bench.exe
ちなみに今回はPHPファイルからexeファイルを作りましたが、dllファイルで出力してApache+Mono環境で動かすこともできるようです。
ベンチマークテスト
せっかくなので、PHPとPhalangerの速度を比較してみましょう。PHPソースコード付属のベンチマークテストZend/bench.phpをMacOSX 10.9上で実行してみました。
PHP7 | PHP 5.6 | Phalanger | |
---|---|---|---|
simple | 0.094 | 0.112 | 0.069 |
simplecall | 0.028 | 0.116 | 0.019 |
simpleucall | 0.054 | 0.112 | 0.021 |
simpleudcall | 0.053 | 0.116 | 0.021 |
mandel | 0.314 | 0.304 | 0.387 |
mandel2 | 0.347 | 0.356 | 0.584 |
ackermann(7) | 0.078 | 0.140 | 0.044 |
ary(50000) | 0.008 | 0.023 | 0.025 |
ary2(50000) | 0.008 | 0.019 | 0.017 |
ary3(2000) | 0.136 | 0.152 | 0.338 |
fibo(30) | 0.181 | 0.374 | 0.151 |
hash1(50000) | 0.017 | 0.029 | 0.116 |
hash2(500) | 0.017 | 0.035 | 0.073 |
heapsort(20000) | 0.067 | 0.092 | 0.116 |
matrix(20) | 0.069 | 0.086 | 0.136 |
nestedloop(12) | 0.156 | 0.199 | 0.115 |
sieve(30) | 0.041 | 0.089 | 0.114 |
strcat(200000) | 0.010 | 0.013 | 0.013 |
Total | 1.677 | 2.365 | 2.356 |
判断しにくい結果になりましたが、トータルで見るとPhalangerとPHP 5.6が同程度、PHP 7との比較だと約1.5倍遅いという結果になりました。とはいえテストによってはPHP7より断然速いものもありますし、Phalangerのメインターゲットである.NET Framework環境では更に高速になるのかもしれません。十分な可能性を持った実装だと言えるでしょう。
互換性
本家のWikiにPhalangerとPHPとの互換性に関する情報がまとめられていますが、言語自体もエクステンションもかなり頑張って追従しているようです。SPL、リフレクション、traitあたりに積み残しがあるものの、それ以外はPHP 5.4まで追いついているようです。
IIS+SQL Server+Phalanger+WordPressを動かしたという記事も見つかりました(参照:「WordPress on .NET with SQL Server is Possimpible using Phalanger 3.0」)。なかなかの変態構成で良いですね。
HHVMと違ってPHPからCソースコードをもらってくることができず、自前実装部分が増えがちなのは不安点ではありますが、実装力(というか根気)でカバーしているようです。たとえば==のキモい挙動もかなり再現できていました(InfやNaNあたりの挙動が違っている程度で、トラブルの原因にはならないと思います)。
実装をチラ見する
PhalangerのソースコードはGitHubで公開されています(参照:DEVSENSE/Phalanger)。これを眺めてみました。
パーサーはGPPGを利用しています。Source/Core.Parsers/Generators/以下を見ると、Lexer.lexとParser.yはPHP本体のものを修正して使っているようです。
演算子や組み込み関数の実装などは完全に新規で書いているようです。==の比較に相当する分だけでも長々とC#コードが記述してあって、真似したくはないけど感心しますね(参照:Source/Core/Comparisons.cs)。