オープンソースプロジェクト
JPHPを紹介します。 これは、JITをサポートするJavaVMの代替PHP実装です。 私は2013年10月にプロジェクトを単独で開始し、4か月後にJVMバイトコードにphpコンパイラを実装しました。 この言語はPHP 5.3のレベルでサポートされ、PHP 5.4および5.5の機能は部分的にサポートされています。 そのイデオロギーでは、プロジェクトはJRubyとJythonに似ています。
私はプロジェクトについて話す小さなプレゼンテーションを用意しましたが、あまり時間はかかりません:
このプロジェクトについてできる限り話したいという願望がありますが、すべてを1つの記事に収めるのは怖いです。 乱雑ではないことを願っています。
プロジェクト目標
JPHPはZend PHPやFacebook HHVMの代替ではありません。CURL、PRCE、PDOなど、すべてのランタイムzend phpライブラリを実装する計画がなかったためです。 プロジェクトを開始した主な理由は次のとおりです。
- 実験だった
- PHPでのJavaライブラリの使用
- JIT + JVMで生産性を向上
- 一貫性のないいZend PHPランタイムをより適切なものに置き換えます
- WebだけでなくPHPでの書き込みを許可する
- Unicodeおよびマルチスレッドのサポートを実装する
技術的な詳細
言語全体はバイトコードを生成するために
ASMライブラリを使用してJavaでゼロから記述され、Groovyなどのすべての一般的なjvm言語で使用されます。 Gradleがビルドシステムとして選択されました。
驚いたことに、Javaテクノロジースタックは、jvm言語を記述するための非常に便利な条件を提供します。 JITでVMを記述する必要はありません。ガベージコレクターとクラスシステムは既に実装されています。クロスプラットフォームについて頭痛の種はありません。また、jvmバイトコード自体は非常に理解しやすいです。 しかし、多くの落とし穴がありました。何よりも、PHP言語自体の魔法によるものです。
JITにより、テストに応じて生産性を1〜10倍、実際のコードで平均1.5〜3倍向上させることができました。 また、コードの高速化に役立つオプティマイザーも実装しました。
PHPの互換性?
言語とライブラリを区別する価値があるため、言語とライブラリのレベルでの互換性は2つの異なるものです。 開発の初期段階で、私はすべてのPHPライブラリを1人に対して適切な互換性で記述することは不可能であることに気付きました。 言語のみに集中することにしましたが、splの自動読み込み、Reflection、ob_ *関数、
<? ... ?>
<? ... ?>
など。
JPHPは、OOP、関数、演算子などのテストを含む、元のZend PHPからの約300以上のユニットテストに合格します。 テストもあります。 これは、言語が適切に機能していることを確認するのに役立ちます。 次に、サポートされている機能をリストします。
- PHP 5.3の言語(gotoを除く)
- 呼び出し可能のタイプヒント(5.4)
- 配列の短い構文(5.4)
Class::{expr}(), (new Foo)->bar()
(5.4)- 試して...最後に(5.5)
- 配列および文字列リテラルの逆参照(5.5)
- foo()[0](5.4)を逆参照する関数配列
- クラス名を取得する
class
システム定数(5.5)
PHP 5.4からの特性の実装途中。
JITとパフォーマンス
どのコードがパフォーマンスに影響すると思いますか? Facebook HHVMに精通しているなら、どれを知っていると思います。 PHPのパフォーマンスに関する主な問題は、変数のグローバルスペース、変数の魔法、実行時に名前で変数にアクセスできる場合の魔法です。 このため、JPHPは同じコードをさまざまな方法でコンパイルできます。 変数に魔法がない場合、コンパイラは変数をインデックスに変換し、実行時にインデックスによってすぐにアクセスします。 例を挙げましょう。
$var = 'foobar'; $x = 'var'; ${$x} = 'chanched';
$global_var = 100500; include 'file.php';
function foobar() { $x = 100500; $var = get_defined_vars();
したがって、実行時に名前で変数を参照することになっている場合、JPHPは変数名のテーブルを保存し、そうでない場合には、インデックスによって変数を保存せず、すぐに参照します。
変数の魔法は、JPHPでコードを約2倍遅くすることです。 Zend PHPでは、コードはすべての条件下で同じように機能します。
オプティマイザー
JPHPオプティマイザーは非常に多くのことを実行できます。ここにその機能の短いリストがあります。
1.定数式 $x = (20 + 30) . 'foobar';
2.静的定数JPHPがコンパイル時に知っている定数があり、
define
を介して宣言された動的定数があり
define
。 静的は、システム定数
__FILE__, __DIR__, __CLASS__
、java拡張定数、
const
介して同じファイル内で宣言される定数です。 それらはすべて、コンパイル時に置き換えることができます。
include __DIR__ . '/core.php';
3.不変の関数とメソッドこれらは結果が変わらない関数またはメソッドであるか、コンパイル中に一度計算できるものであり、グローバル環境に影響を与えないため安全です。
for ($i = 0; $i < 100500; $i++){ $x = cos(1) + 3;
この例では、関数cos()は体系的で不変であり、関数に渡されるパラメーターは定数であるため、cos(1)の結果は決して変化しません。
パラメーターを持たず、定数式を返す、プログラマーによって宣言された不変のインクルード関数/メソッド。 JPHPでそのような関数を呼び出すことは、定数の呼び出しに速度が匹敵します。例えば:
function getVersion(){ return '1.0'; } $x = getVersion();
4.不可能な条件ifまたはelseifで定数式がすべてfalseの場合、コンパイラは不要な条件をまったく拒否します。 これまでのところ、elseおよびelseifがサポートされている場合のみ。 たとえば、これは非常に便利です。
if (TRACE_ENABLED){
クラス、関数、バイトコードをキャッシュしていますか?
JPHP作業モデルを使用すると、コンパイルされたコードをメモリに保存できます。 クラスと関数。 コンパイルおよびロードされたクラスは繰り返し使用されます。 将来的には、PHP自体でPhalconに劣らないパフォーマンスフレームワークであるhttpサーバーを作成できるようになります。 データはリクエスト間で簡単に保存でき、httpサーバーはphp自体に書き込むことができます。これについては以下で説明します。
JPHPには、スクリプトを実行するための隔離された環境を作成できる特別な
Environmentクラスがあります。これは、runkit拡張のサンドボックスのようなものです。 そのような各環境には、独自のクラス、関数、およびグローバル変数のセットがあります。
- 環境-スクリプトを実行するための分離された環境
- Runkitのサンドボックスのように
- 柔軟なマルチスレッド実装に必要
- HOTリロードワークフローを整理できます
- 環境は互いに相互作用することができます
以下の例でこのクラスを使用して、マルチスレッドhttpサーバーを編成します。
どうやって試すの? テストプロジェクトを構築しますか?
これを行うには、Java(1.6+)およびGradleビルドシステム(1.4+)をインストールする必要があります。 gitリポジトリからソースをダウンロードします。 JetBrains IDEAでは、build.gradleからプロジェクトをインポートできます。 この段階では、
jphp-example-project
フォルダーにテストプロジェクトがあります。 このプロジェクトは実行可能なjarファイルにコンパイルされ、その中にphpソースがあります。 jarが起動すると、
bootstrap.php
ファイルが実行されます。 次のコマンドを使用してjarをビルドできます。
gradle jar
またはすぐに実行します:
gradle exampleStart
プロジェクトは、jarファイルの
build/libs/
フォルダーにアセンブルされます。
GUI? プログラム?
また、Swing(GUI用のJavaライブラリー)のラッパー拡張機能も作成しました。 クロスプラットフォームのGUIプログラムを作成できます。 Swingに精通している人のために、私は安心したいです-私はAPIとレイアウトシステムをかなり単純化しました。 GUIの小さなウィンドウ:
use php\lang\System; use php\swing\SwingUtilities; use php\swing\UIForm; use php\swing\UIDialog; use php\swing\UIButton; SwingUtilities::invokeLater(function(){ $form = new UIForm(); $form->size = [500, 500]; $form->moveToCenter(); $form->visible = true; $p = new UIButton(); $p->size = [300, 40]; $p->align = 'top'; $p->h = 30; $p->text = ''; $p->on('click', function(){ UIDialog::message('', ''); }); $form->add($p); $form->on('windowClosing', function(){ System::halt(0); }); });
マルチスレッドHTTPサーバー?
JPHPでは、マルチスレッドhttpサーバーを作成できます。 これを行うために、私は
Socket
および
ServerSokect
、および
Thread
スレッドクラスをインポートしました。
use php\concurrent\ExecutorService; use php\io\IOException; use php\lang\Environment; use php\net\ServerSocket; $server = new ServerSocket(); $server->bind('localhost', 8080); $service = ExecutorService::newFixedThreadPool(5);
このようなサーバーはコンテンツを非常に迅速に提供し、abユーティリティでテストしましたが、結果は印象的です。 私のマシン(Java 7、i3、Windows 7)では、このようなサーバーは1秒あたり4000〜5000のリクエストを処理できます(
ab -n50000 -c100 localhost
ab -n50000 -c100 localhost
)に該当します。
次は?
私は自分でJPHPを開発し、リリースして、すべての言語機能をPHP 5.5に実装する予定です。 おそらく、Androidとの互換性の実装を試みます(JRuby用のRobotoの例に従って)。 私は名前空間とOOPに基づいて通常の拡張機能を実装しますが、部分的には既に何かを実装しています-ストリーム、ソケット、GUI、JSON。
プレゼンテーションの残りの部分を参照してください。 ご清聴ありがとうございました。