MessagePackのPHP用拡張モジュールを試してみた

久しぶりに時間が出来たのでMessagePackをPHP拡張モジュールとして追加してみました。

MessagePackはgithubでダウンロード出来ます。
PHP以外の言語に追加する場合も同じ場所からダウンロード出来ます。便利ですね!

MessagePack - github -< https://github.com/msgpack >

サクッと追加出来るのも良いですね!
手順は以下の通りです。

> githubからMessagePackを取得
# git clone https://github.com/msgpack/msgpack-php.git

> PHPの拡張モジュール追加準備
# phpize
-----
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
-----

> チェック・Makefile生成
# ./configure
-----
configure: creating ./config.status
config.status: creating config.h
config.status: executing libtool commands
-----

> コンパイル
# make
-----
Build complete.
-----

> インストール
# make install
-----
Installing shared extensions:     /usr/lib/php/modules/
Installing header files:          /usr/include/php/
-----

> PHPの拡張設定ファイルを追加

> messagepackを読み込む
# vi /etc/php.d/msgpack.ini
-----
extension=msgpack.so
-----

> Apacheの再起動
# /etc/rc.d/init.d/httpd restart

適当に以下のファイルを作成してJSONと比較してみました。
シリアライズとデシリアライズを行っているので不要な場合はコメントアウトしてください。

<?php

$limit  = 50;
$pass   = 0;
$result = array();
for ($i = 1; $i <= $limit; $i++) {

	// random string.
	$random_string   = randomString(100000);

	// MessagePack.
	$start           = getTimes();
	$tmp             = msgpack_serialize($random_string);
	$res             = msgpack_unserialize($tmp);
	$end             = getTimes();
	$result['m'][$i] = benchMark($start, $end);

	// Json.
	$start           = getTimes();
	$tmp             = json_encode($random_string);
	$res             = json_decode($tmp);
	$end             = getTimes();
	$result['j'][$i] = benchMark($start, $end);
	
	// print.
	if (!$pass) {
		$sign = benchSign($result['m'][$i], $result['j'][$i]);
		print sprintf("%s\tM:%s\t%s\tJ:%s\n", $i, $result['m'][$i], $sign, $result['j'][$i]);
	}

}

if (!$pass) print "-----------------\n";

// max.
$total['m'] = max($result['m']);
$total['j'] = max($result['j']);
$sign       = benchSign($total['m'], $total['j']);
print sprintf("max\tM:%s\t%s\tJ:%s\n", $total['m'], $sign, $total['j']);

// avg.
$total['m'] = number_format(array_sum($result['m']) / $limit, 10);
$total['j'] = number_format(array_sum($result['j']) / $limit, 10);
$sign       = benchSign($total['m'], $total['j']);
print sprintf("avg\tM:%s\t%s\tJ:%s\n", $total['m'], $sign, $total['j']);

exit(0);

function benchSign ($left, $right) {
	$sign = '';
	if ($left === $right) $sign = '==';
	else if ($left > $right) $sign = '>';
	else $sign = '<';
	return $sign;
}
function benchMark ($start, $end) {
	return number_format(($end[0] - $start[0]) + ($end[1] - $start[1]), 10);
}
function getTimes () {
	return array(time(), microtime());
}
function randomString ($length, $res = null, $i = 0) {
	$str = array_merge(range('a', 'z'), range('0', '9'), range('A', 'Z"'));
	for ($i; $i < $length; $i++) {
		$rand = rand(0, count($str));
		$res .= isset($str[$rand]) ? $str[$rand] : '' ;
	}
	return $res;
}

結果は以下の通りです。

1       M:0.0005350000  <       J:0.0045480000
2       M:0.0000520000  <       J:0.0040560000
3       M:0.0001310000  <       J:0.0039100000
4       M:0.0000510000  <       J:0.0033410000
5       M:0.0000460000  <       J:0.0031090000
6       M:0.0000630000  <       J:0.0031980000
7       M:0.0000450000  <       J:0.0032470000
8       M:0.0000490000  <       J:0.0032170000
9       M:0.0000500000  <       J:0.0032100000
10      M:0.0000500000  <       J:0.0037790000
11      M:0.0000460000  <       J:0.0033240000
12      M:0.0000480000  <       J:0.0032200000
13      M:0.0000500000  <       J:0.0032390000
14      M:0.0000520000  <       J:0.0031910000
15      M:0.0000440000  <       J:0.0032710000
16      M:0.0000740000  <       J:0.0032020000
17      M:0.0000520000  <       J:0.0031850000
18      M:0.0000540000  <       J:0.0032210000
19      M:0.0000630000  <       J:0.0031990000
20      M:0.0000480000  <       J:0.0032300000
21      M:0.0000500000  <       J:0.0032070000
22      M:0.0000490000  <       J:0.0031880000
23      M:0.0000540000  <       J:0.0033780000
24      M:0.0000480000  <       J:0.0031370000
25      M:0.0000410000  <       J:0.0032060000
26      M:0.0000520000  <       J:0.0036880000
27      M:0.0001430000  <       J:0.0038180000
28      M:0.0001470000  <       J:0.0032570000
29      M:0.0002290000  <       J:0.0037570000
30      M:0.0001640000  <       J:0.0032160000
31      M:0.0000500000  <       J:0.0035160000
32      M:0.0000490000  <       J:0.0036790000
33      M:0.0001490000  <       J:0.0039440000
34      M:0.0001640000  <       J:0.0031720000
35      M:0.0002360000  <       J:0.0037250000
36      M:0.0001640000  <       J:0.0038990000
37      M:0.0001500000  <       J:0.0039100000
38      M:0.0001630000  <       J:0.0033860000
39      M:0.0000490000  <       J:0.0031770000
40      M:0.0000440000  <       J:0.0037490000
41      M:0.0001570000  <       J:0.0031860000
42      M:0.0002380000  <       J:0.0039040000
43      M:0.0001610000  <       J:0.0039150000
44      M:0.0001570000  <       J:0.0038990000
45      M:0.0001620000  <       J:0.0033680000
46      M:0.0000540000  <       J:0.0037850000
47      M:0.0000490000  <       J:0.0032220000
48      M:0.0001580000  <       J:0.0031660000
49      M:0.0000450000  <       J:0.0039660000
50      M:0.0001500000  <       J:0.0039230000
-----------------
max     M:0.0005350000  <       J:0.0045480000
avg     M:0.0001025800  <       J:0.0034848000

こうして実際に比較してみるとやっぱり速いな〜と思いました。