MessagePack

  • KJ
  • 2014/04/11

PHP の MessagePack 拡張を次の 2 点を重視して改良しました。

  • 新仕様に対応
  • アンシリアライズ処理速度の向上

現状

MessagePack とは

MessagePack は効率の良いシリアライズライブラリになります。

詳細はプロジェクトページにてご確認ください。

PHP のシリアライズ

PHP でシリアライズ処理を行う代表的なものには次のものがあります。

  • serialize/unserialize

    PHP の標準シリアライザです。

  • igbinary

    バイナリベースの PHP シリアライザです。(PECL)

  • Msgpack for PHP

    現状の PHP の MessagePack によるシリアライザです。(PECL)

  • MessagePack 改良版拡張モジュール

    以前、私が作成 MessagePack の PHP 拡張です。

    Msgpack for PHP はアンシリアライズの処理を template を用いて行っているのですがこれでは配列の処理があまりうまく扱えないのでこの辺りを中心に改良したものになります。

また、MessagePack は仕様が若干変更されたのですが PHP 拡張のどちらとも新しい仕様には対応しておりませんでした。仕様はこちらにてご確認ください。

開発方針

MessagePack 改良版拡張モジュールをベースに最新の仕様に対応に対応して、アンシリアライズの速度が遅い (msgpack_unpack slow #26)ので処理速度の向上を目標として開発をしました。

シリアライズオブジェクト

PHP の型と MessagePack のシリアライズ型の対応は次のようにしています。

PHP MessagePack
論理 boolen true/false
整数 integer int/uint/fixint
浮動小数点 float float
文字列 string str
NULL NULL nil
配列 array map
クラス object ext
参照 referecne ext

PHP 配列は明示的に array と map を分けていないため、まとめて map で処理します。

クラス

クラスはフォーマットとして ext を使用しています。

  • クラスオブジェクト

    拡張タイプ 1 で、データは「 クラス名 + プロパティ数 + ( プロパティアクセス + プロパティ名 + プロパティ値 ) * プロパティ数」の構造になります。

    フォーマット
    ext type = 1
    str クラス名
    int プロパティ数
    positve fixint プロパティアクセス (1 = protected, 2 = privated): 省略可
    str プロパティ名
    any プロパティ値
  • Serializable クラスオブジェクト

    拡張タイプ 2 で、データは「 クラス名 + シリアライズデータ 」の構造になります。

    フォーマット
    ext type = 2
    str クラス名
    str シリアライズデータ

参照

参照もフォーマットとして ext を使用しています。

  • 参照元

    後述する参照型の元になる値を示します。拡張タイプ 3 で「 任意の型 」の構造になります。

    フォーマット
    ext type = 3
    any value
  • 参照型

    • serialize 関数の R と等価な参照型。

      拡張タイプ 4 で「 参照番号 」の構造になります。

      フォーマット
      ext type = 4
      int 参照番号
    • serialize 関数の r と等価な参照型。

      拡張タイプ 5 で「 参照番号 」の構造になります。

      フォーマット
      ext type = 5
      int 参照番号

インストール

PHP 拡張のビルドを行うためには次のものが必要になります。

  • phpize コマンド
  • PHP ヘッダファイル
  • gcc 等

ディストリビューションでは php-devel 等のパッケージをインストールしておけば問題ないと思います。

ビルドは次のコマンドを実行して行います。

$ curl -sL https://github.com/karakurihiden/msgpack-php/archive/v0.1.1.tar.gz -o msgpack-php-0.1.1.tar.gz
$ tar xf msgpack-php-0.1.1.tar.gz
$ cd msgpack-php-0.1.1
$ phpize
$ ./configure
$ make
$ make test
$ make install

msgpack.so が PHPL の modules ディレクトリ (/usr/lib64/php/modules 等) にインストールできたら、設定ファイル (/etc/php.d/msgpack.ini 等) を作成します。

msgpack.ini

extension=msgpack.so

php -m を実行して msgpack という文字が表示されればインストール完了です。

Apache モジュールや PHP FPM を使用している場合はそれぞれのサービスも再起動させてください。

ベンチマーク

評価対象

  • default

    PHP の標準シリアライザ。

    • serialize
    • unserialize
  • igbinary

    igbinary によるシリアライザ。

    • igbinary_serialize
    • igbinary_unserialize
  • msgpack

    Msgpack for PHP によるシリアライザ。(現状の PECL にある MessagePack 拡張)

    • msgpack_serialize
    • msgpack_unserialize
  • msgpacki

    MessagePack 改良版拡張モジュール によるシリアライザ。

    • msgpacki_serialize
    • msgpacki_unserialize
  • develop

    今回、開発したもの MessagePack 拡張によるシリアライザ。

    • MessagePack\serialize
    • MessagePack\unserialize

    バージョン 0.1.0 にて実行しています

テスト環境構築

各対象のソースを取得して拡張をビルドします。

  • igbinary

    $ git clone --depth=1 https://github.com/igbinary/igbinary.git
    $ cd igbinary
    $ phpize && ./configure && make
    $ cd ..
    
  • msgpack

    $ git clone --depth=1 https://github.com/msgpack/msgpack-php.git msgpack
    $ cd msgpack
    $ phpize && ./configure && make
    $ cd ..
    
  • msgpacki

    $ git clone --depth=1 https://github.com/kjdev/php-ext-msgpacki.git msgpacki
    $ cd msgpacki
    $ phpize && ./configure && make
    $ cd ..
    
  • develop

    $ git clone --depth=1 https://github.com/karakurihiden/msgpack-php.git
    $ cd msgpack-php
    $ phpize && ./configure && make
    $ cd ..
    

テストファイルを作成します。

テストファイルは msgpack_unpack slow #26 で使われているファイルをベースにして作成しました。

テストコード: benchmark-test.php

テスト実行用スクリプトを作成します。

実行スクリプト: benchmark.sh

テスト実行用スクリプトでは

PHP_INI_SCAN_DIR=. php -d extension_dir=./msgpack-php/modules -d extension=msgpack.so  benchmark-msgpack.php develop $func $type

のように PHP_INI_SCAN_DIR, extension_dir, extension を指定して各拡張を指定して benchmark-msgpack.php を実行しています。

テスト実行

$ curl -sLO http://hiden.samurai-factory.jp/download/php/msgpack/benchmark.sh
$ bash benchmark.sh build

シリアライズテスト結果

  • 文字列 (string)

serialize-string

  • 整数 (integer)

serialize-integer

  • 論理 (boolean)

serialize-boolean

  • 浮動小数点 (float)

serialize-float

  • 配列 (array)

serialize-array

  • 連想配列 (map)

serialize-map

  • 混合配列 (mixed)

serialize-mixed

  • オブジェクト (object)

serialize-object

  • 複合 (all)

serialize-all

アンシリアライズテスト結果

  • 文字列 (string)

unserialize-string

  • 整数 (integer)

unserialize-integer

  • 論理 (boolean)

unserialize-boolean

  • 浮動小数点 (float)

unserialize-float

  • 配列 (array)

unserialize-array

  • 連想配列 (map)

unserialize-map

  • 混合配列 (mixed)

unserialize-mixed

  • オブジェクト (object)

unserialize-object

  • 複合 (all)

unserialize-all

結果

シリアライズの処理性能がまだよくなっていないがアンシリアライズでは概ねよい性能が出すことができました。

ダウンロード

リポジトリ

github.com/karakurihiden/msgpack-php

ソースファイル

msgpack-php-0.1.1.tar.gz

RPM パッケージ

CentOS 6

php-pecl-msgpack-0.1.1

CentOS 6 (Remi enable)

php-pecl-msgpack-0.1.1

Fedora 20

php-pecl-msgpack-0.1.1

Windows (DLL)

VC11 x86 Non Thread Safe: PHP 5.5 (5.5.12)

VC11 x86 Thread Safe: PHP 5.5 (5.5.12)