igbinary vs serialize vs json_encode

最近看到memcached扩展支持额外的序列化方式 — igbinary,这是一个未收录到pecl的php扩展,它提供的两个主要方法:

    • igbinary_serialize
    • igbinary_unserialize

据称可以用它来代替php自带的序列化函数serialize,性能更好,而且占用的字节数也更少。下面我就 igbinary ,serialize ,json_encode三者的性能做了一个简单的测试。

测试

以一个包含1000000个元素的数组做为原始数据,分别以json, serialize, igbinary进行序列化和反向操作。


<?php
ini_set('memory_limit', '512m');
$array = array_fill(0, 1000000, rand(1, 9999));

$start = microtime(true);
$export = json_encode($array);
$end = microtime(true);
$duration = $end - $start;
print('JSON Encode: ' . $duration . PHP_EOL);

$start = microtime(true);
$import = json_decode($export);
$end = microtime(true);
$duration = $end - $start;
print('JSON Decode: ' . $duration . PHP_EOL);

$start = microtime(true);
$export = serialize($array);
$end = microtime(true);
$duration = $end - $start;
print('Serialize: ' . $duration . PHP_EOL);

$start = microtime(true);
$import = unserialize($export);
$end = microtime(true);
$duration = $end - $start;
print('Serialize: ' . $duration . PHP_EOL);

$start = microtime(true);
$export = igbinary_serialize($array);
$end = microtime(true);
$duration = $end - $start;
print('Igbinary Serialize: ' . $duration . PHP_EOL);

$start = microtime(true);
$import = igbinary_unserialize($export);
$end = microtime(true);
$duration = $end - $start;
print('Igbinary Serialize: ' . $duration . PHP_EOL);
?>

测试结果

JSON Encode: 0.084825992584229
JSON Decode: 0.34976410865784
Serialize: 0.38241410255432
Serialize: 7.7904229164124
Igbinary Serialize: 0.046916007995605
Igbinary Serialize: 0.23396801948547

从测试结果来看,速度方面优先级排列为 igbinary > json > serialize。同时我们也可以看到,php原生的serialize在对大对象进行反向操作时,速度真是掉队一大截了。

占用字节数对比

    • json: 5000001
    • serialize: 15888902
    • igbinary: 7868681

在没有中文字符的情况下,json胜出,igbinary次之,serialize又被甩了几条街。

一图顶千言

柱状图越矮小的性能越好
igbinary vs serialize vs json_encode 速度比较

17 Replies to “igbinary vs serialize vs json_encode”

  1. 你的程序我改了一下,把igbinary 改成了 hprose,注意,hprose 是用 php 实现的,还不是用 C 实现到模块。但是反序列化到效率比 PHP 和 JSON 都高到惊人。

    Hprose Serialize: 0.676019906998
    Hprose Unserialize: 4.00543212891E-5
    Serialize: 0.715716123581
    Unserialize: 8.06125807762
    JSON Encode: 0.158088207245
    JSON Decode: 2.83418416977

    注意Hprose反序列化时间最后面那个 E-5,是 PHP 反序列化速度的200000倍,是JSON反序列化速度的70000倍。

  2. 能给出hprose更详细的测试结果吗?很好奇,比如:

    • 包含中文的内容序列化之后占用的字节数
    • 大数组/小数组
    • 大对象/小对象
  3. 不好意思,上面测试结果有误!测试程序不对,我不小心把::写成.了,所以程序执行时间不对。下面是我修改后的程序和测试结果,差别确实没那么大,除了长度:
    [code]

    [/code]

    Hprose Length: 300606
    Hprose Serialize: 4.48698115349
    Hprose Unserialize: 1.80469584465
    PHP Length: 61088901
    Serialize: 0.251639127731
    Unserialize: 0.144748926163
    JSON Length: 119100001
    JSON Encode: 2.24326896667
    JSON Decode: 13.0224480629

  4. include('hproseIO.php');
    ini_set('memory_limit', '512m');
    $array = array_fill(0, 100000, "汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字");
    $start = microtime(true);
    $export = HproseFormatter::serialize($array);
    $end = microtime(true);
    $duration = $end - $start;
    print('Hprose Length: ' . strlen($export) . PHP_EOL);
    print('Hprose Serialize: ' . $duration . PHP_EOL);
    $start = microtime(true);
    $import = HproseFormatter::unserialize($export);
    $end = microtime(true);
    $duration = $end - $start;
    print('Hprose Unserialize: ' . $duration . PHP_EOL);
    $start = microtime(true);
    $export = serialize($array);
    $end = microtime(true);
    $duration = $end - $start;
    print('PHP Length: ' . strlen($export) . PHP_EOL);
    print('Serialize: ' . $duration . PHP_EOL);
    $start = microtime(true);
    $import = unserialize($export);
    $end = microtime(true);
    $duration = $end - $start;
    print('Unserialize: ' . $duration . PHP_EOL);
    $start = microtime(true);
    $export = json_encode($array);
    $end = microtime(true);
    $duration = $end - $start;
    print('JSON Length: ' . strlen($export) . PHP_EOL);
    print('JSON Encode: ' . $duration . PHP_EOL);
    $start = microtime(true);
    $import = json_decode($export);
    $end = microtime(true);
    $duration = $end - $start;
    print('JSON Decode: ' . $duration . PHP_EOL);
  5. @andot 我用上面的汉字测试了一下,这是包含10万个元素的数组,encode的时候居然是serialize占优,而igbinary慢了快一半。但是反序列化的时候,igbinary远胜。另外igbinary序列化之后字节数,也是远小于其它两个的,但是没赶上hprose。

    总体来看,igbinary很有优势:)

    JSON Encode: 1.0289189815521; size: 119100001
    JSON Decode: 2.2438578605652
    Serialize: 0.091415882110596; size: 61088901
    Serialize: 0.11619782447815
    Igbinary Serialize: 0.16038608551025; size: 569276
    Igbinary Serialize: 0.067336082458496

  6. 嗯,igbinary是二进制序列化方式,不过我看了一下它的类型跟PHP的类型绑定的有些紧密,不是很适合跨语言实现,不过在PHP里面用确实还是不错的。hprose目前的实现是纯PHP写的,时间效率上低一些是预料之中的(今天早上测试那个错误结论实在让我自己感觉也不可思议,哈哈),等hprose 1.0版本的文档全部完成之后,我们会在下一个版本中也加入C模块实现方式,到时候时间效率上应该也会有很大提升的。

  7. 建议把序列化方式改成可配置的,这样php程序员就有可能在hprose使用其它的序列化方式提高效率。

  8. 序列化在远程调用中并不是独立的一个部分,它牵扯到类型映射问题,还有其它许多方面的问题,不是可以随便替换的。

  9. 这个模块有没有其他语言的实现?比如py?

    我在几个应用之间共享session,有的应用是python实现的,找了一个开源的PHPUnserialize类。

    php自带的serialize确实很垃圾,又长又慢。

    这几天碰到个郁闷的问题,py那个类有bug,在session里面加了个key-1-1这样的键,导致py里面session解不出来。后来发现是它的正则有问题。

  10. 这个数据集太大了
    对小规模数据,特别是 20-50个元素的数组,进行序列化,Serialize的优势特别明显,最慢的是json

  11. Hprose Serialize: 4.48698115349
    Serialize: 0.251639127731
    Hprose Unserialize: 1.80469584465
    Unserialize: 0.144748926163
    你这不对啊,明显是php serialize/unserialize比hprose快了17倍编码/12倍解码
    应该说php原生序列化比hprose速度快的惊人才对,差了10倍数量级!
    而且andot的hprose for php也不是开源的,看不到源码,
    从你最后一次提供的对比数据来看,hprose比php native要慢很多

  12. Hprose Length: 300606
    PHP Length: 61088901

    而且你这个数据长度也明显有问题,hprose的序列化数据肯定是经过压缩的了
    这个数据长度没法真实反映hprose的空间占用,得换一个文章类的字串测试
    但是我预计hprose的空战占用也不比ig占多大便宜,看过hprose的序列化后的数据,
    在序列化超大字符串时候,hprose空间占用比php serialize少不了多少(少了几个引号和分号)

    实际上hprose序列化是php serialize的精简版,去掉了key-value之间的引号和分号,
    由于是基于php-code的serilize,编码格式又极其接近php native serialize
    结论是hprose for php序列化速度不可能比php native serialize快

    当然如果将hprose serialize用c编译成php extension就另当别论了

  13. 大小比拼开始:
    1K:msgpack_serialize:127
    1K:serialize:226
    1K:igbinary_serialize:150
    1M:serialize:1168207
    1M:msgpack_serialize:623666
    1M:igbinary_serialize:198548
    速度比拼开始:
    循环100次序列化,反序列化小数组serialize:0.00017285346984863
    循环100次序列化,反序列化小数组msgpack_serialize:0.00012588500976562
    循环100次序列化,反序列化小数组igbinary_serialize:0.00017714500427246
    循环100次序列化,反序列化大数组serialize:0.54277181625366
    循环100次序列化,反序列化大数组msgpack_serialize:0.3210928440094
    循环100次序列化,反序列化大数组igbinary_serialize:0.29830503463745
    只反小数组序列化比拼开始:
    反序列化小数组serialize:0.011802911758423
    反序列化小数组msgpack_serialize:4.0054321289062E-5
    反序列化小数组igbinary_serialize:3.4093856811523E-5
    只反大数组序列化比拼开始:
    反序列化大数组serialize:0.26046895980835
    反序列化大数组msgpack_serialize:0.24461698532104
    反序列化大数组igbinary_serialize:0.21050691604614

  14. 我觉得php的unserialize的速度应该会快很多啊,因为它序列化的时候都有给每一个数组的内容记录长度,所以在反序列化的时候会直接分配长度,会加快反序列化的速度。不知道博主的测试有没有一个具体的定论呢?

Leave a Reply

Your email address will not be published.