Hatena::ブログ(Diary)

hnwの日記 このページをアンテナに追加 RSSフィード

[プロフィール]

2014年12月29日(月) PHPを高速化するRecki-CTとは一体何なのか このエントリーを含むブックマーク このエントリーのブックマークコメント

@ircmaxellさん作の「Recki-CT」を試してみたので紹介します。作者によるブログ記事ircmaxell’s blog: Introducing Recki-CT」によれば処理によってはHHVMやHippy VMより速いらしいのですが、この記事だけでは詳細がよくわからずモヤモヤしていました。今回ソースコードまで確認してみて、前作のPHPPHPを超える変態作品だとわかりました(参照:「PHPPHPがド変態であることに今さら気づいた」)。


Recki-CTを試してみる

Recki-CTの概要を説明すると、既存のPHP関数に型情報のアノテーションを記述して呼び出し方を少し変えることで、その関数JITコンパイルしてネイティブコードとして実行するPHPライブラリです。JITコンパイルにはlibjitのPHPバインディングであるJIT-Fuを利用しています。


では、さっそく試してみましょう。次のコード中のgcd関数JITコンパイルで高速化したいとします。


<?php
function gcd($x, $y)
{
    if ($x === $y) {
        return $x;
    } else if ($x < $y) {
        return gcd($x, $y - $x);
    } else {
        return gcd($x - $y, $y);
    }
}

$z = gcd(407074349875, 691666152);

これに対してRecki-CT適用すると次のようなコードになります。


<?php
require_once __DIR__ . '/vendor/autoload.php';

use ReckiCT\Jit;

/**
 * @param int $x
 * @param int $y
 * @return int
 */
function gcd($x, $y)
{
    if ($x === $y) {
        return $x;
    } else if ($x < $y) {
        return gcd($x, $y - $x);
    } else {
        return gcd($x - $y, $y);
    }
}

$gcd = Jit::JitFu('gcd');
$z = $gcd(407074349875, 691666152);

このように、十分少ない変更で既存の関数gcdをJITコンパイル対応にできます。既存の関数JIT-Fuに書き換えるのはかなり面倒なので、これだけでも面白い成果だと言えるでしょう(参照:「PHPのlibjitバインディングであるJIT-Fuを試してみた」)。


Recki-CTの中身

上の挙動だけ見ると、Recki-CTPHPからJIT-Fuへのトランスレータなのかな、と考えてしまいます。しかし、Recki-CTはそれよりずっと野心的なプロジェクトです。Recki-CTの処理は次のようになっています。



僕自身はコンパイラに詳しいわけではないのですが、真面目なコンパイラ実装と同様の処理を行っていると考えてよさそうです。


また、上の処理で中間表現(IR)を作るところまではJIT-Fuと全く無関係に動作します。言い方を変えると、コンパイラとしてのRecki-CTにとってJIT-Fuは対応アーキテクチャの一つでしかありません。今後JIT-Fu以外のJITコンパイラ実装が出てきても差し替えは容易ですし、PHPやその他の言語で出力することもできます。最適化フェーズで使える情報が多いため、他の方法ではできない最適化の可能性がある点も魅力ですね。


まとめ

トラックバック - http://d.hatena.ne.jp/hnw/20141229
ページビュー
1310574