PHPのextensionをCで直接書く方法(公式)とZephirで書く方法の2パターンで作ってみました。

Cで作る

まずはPHPのソースをダウンロード

extensionのスケルトンフレームを作成してビルド

config.m4は以下のコメントアウト(dnl)を削除すればOK

ビルド後は以下のようにして実行可能(もちろんphp.iniにextensionのパスを入れてモジュールを読み込んでもOK)

Zephirで作る

Zephirのインストール

プロジェクトを作成

クラスの作成(zephirhello/hello.zep)

以下のコマンドでZephirからCのコードを作成(Generate)、Cのコードをビルド(Compile)、モジュールのインストール(Install)を行います。

ただし、Mac(El CapitanやSierra)で開発する場合はRootlessのセキュリティ機能によって/usr以下にインストールすることができないため、build時に以下のエラーが発生します。

この場合は、インストール(=ファイルの移動)はせずに、php.iniにコンパイルしたモジュールへのフルパスを書けばOKです。

上記のやり方だと、モジュールのインストールは不要になるので、以下のコマンドでビルドまで行えばOKです。

また、re2cがインストールされていないと、コンパイル時に以下のエラーが発生します。

OS Xの場合はHomeBrewでre2cをインストールすればOKです。

名前空間とディレクトリ、クラス名の構成があっていない場合もエラーが発生します。

上記のエラーは名前空間Utils、クラス名HelloWorldが指定されているので、ファイル構成がutils/helloworld.zepにならないといけないのに、zephirhello/hello.zepとなっているのが原因になります。この場合は、ファイル構成を変更するか、名前空間、クラス名を変更すれば良いです。

モジュールのビルド及びphp.iniでのモジュール設定が完了したら、以下のようにしてクラス、メソッドを呼び出し可能です。

phpinfoでモジュールが読み込まれていることも確認できます。

ベンチマーク(準備)

再帰呼び出しのフィボナッチ数列のロジックでベンチマークを以下のパターンで取ってみました。

  • 素のPHP
  • Cで書いたExtensionを利用したPHP
  • Zephirで書いたExtensionを利用したPHP
  • Ruby(参考)
  • Python(参考)

PHP

PHP(C)

PHP(Zephir)

Ruby

Python

ベンチマーク(結果)

まとめるとこんな感じ。

パターン Index  時間 
PHP(5.6.23) 33 9.93s
PHP(5.6.23、C) 40 0.66s
PHP(5.6.23、Zephir) 33 11.95s
Ruby(2.2.4) 40 14.26s
Python(2.7.11) 40 42.46s

 

PHPはIndex: 33の計算でも10秒近くかかります。40だと1000秒近くかかりそうだったのでPHPのベンチマークはここで断念。

extensionのCで書いたものはIndex: 40で1秒かかりません。やはり早いです。

Zephirで作ったものは素のPHP同様、Index: 33で10秒かかっていたのでここで断念。PHP版とそんなに変わらないみたいですね…。

Rubyで書いたものはIndex: 40で14.5秒程度。

PythonはIndex: 40で45秒程度。3系も似たような結果でした。

参考URL