PHP 对数组进行压缩编码, 哪种最好?

Tuesday 发布于 2013/08/12 15:38
阅读 1K+
收藏 5
PHP
# implode 不支持多维数组! base64_encode压缩性能基本上为0
$s = base64_encode(implode(',',range(1,10000)));
echo strlen($s);

echo '<br />';

# serialize 序列化, 似乎最兼容.可产生多三倍的大小.
$s = serialize(range(1,10000));
echo strlen($s);

echo '<br />';

# json_encode 结构最佳, 性价比高.
$s = json_encode(range(1,10000));
echo strlen($s);
exit();
加载中
0
hylent
hylent

压缩?

试过 $str = var_export($arr, true); 么?

写入 file_put_contents($path, "<?php return $str;", LOCK_EX);

读取 $arr = require $path;

hylent
hylent
哦 高并发可以不用文件存储 读取的时候可以eval 我就提供一个方法 json调用php之外的模块 var_export出来的php本身认识
Tuesday
Tuesday
这种方案已经被抛弃, 并发中最容易出问题. 你想想, 有人在file_put_contents, 有人在inculde
0
王枢昊
王枢昊

serialize 不是太好,有时候会反序列化不回来

个人觉得还是json_encode+base64编码比较好,能跨平台,体积又不会太大

mark35
mark35
回复 @Tuesday : addslashed()才是对浮点数有损压缩(但解压出来基本是原值),json_encode()对浮点数压缩是无损的
Tuesday
Tuesday
json_encode+base64 容量中等吧, 基本上没压缩, 只能说算是打包. json_encode 对元数据似乎有损, 如浮点数之类.
0
Liuxd
Liuxd
楼主试过msgpack否?
Tuesday
Tuesday
其它模块的话, 可能不方便, 我的程序是公共的, 可能有用户没有权限安装其它模块.
0
durban
durban
json格式化  兼容性好  serialize的话,在php之间是不错的
durban
durban
回复 @Tuesday : 不会的,你用了就知道了,这个跟版本没有关系的
Tuesday
Tuesday
json会不会根据php版本不同, 结果不同?
0
wx---羊毛联盟
wx---羊毛联盟
json对字典是无序的,数组是有序的。
wx---羊毛联盟
wx---羊毛联盟
@Tuesday 会影响字典的顺序。 不会改变数组的。
Tuesday
Tuesday
json会影响数组顺序?
0
酒逍遥
酒逍遥

这都不是压缩....序列化而已...本质上就是把数组转换成字符串的形式

序列化的话json_encode 是不错的.


Tuesday
Tuesday
回复 @酒逍遥 : 序列化增大了容量, 我想用json, 但又怕有兼容问题, 如浮点数, 排序之类的.
酒逍遥
酒逍遥
回复 @Tuesday : php 4 5 应该都可以用..不过这个也只是压缩字符串.不能压缩数组..可以把数组先序列化成字符串,然后再压缩
Tuesday
Tuesday
压缩函数: gzcompress 是不是所有php版本都能用? 还是需要开启gzip压缩功能?
0
f
f223156

如果不跨语言, 语言本身提供的serialize方式当然是相对最优解, json_encode只是为了方便ajax应用的需要, 在php 5.2以后加进去的, 并不是php本身提倡使用的序列化方式.
主楼的测试数据太简单, 实际跑起来复杂点的结构肯定json占用数据大, 像mongo这类json做表现的nosql db实存的还是bson,不是json; 而且json_encode比serialize慢, 极端情况下甚至慢几十倍, json的优点就是前后端通讯、跨语言和可读性, 其他没有了.
serialize反序列化出错一般都是数据库表用了text, 再加addslashed导致的, 用blob和参数绑定就不会有什么问题了.

<?php
@set_time_limit(0);
if(php_sapi_name()!=='cli') {
    header('Content-Type:text/plain');
}

$data = array('data'=>file_get_contents('http://www.oschina.net/question/998019_121505'));


function benchmark($function, $times=1000){
    $started_at = microtime(1);
    $data = null;
    for($i=0; $i<$times; $i++){
        $data = $function();
    }
    printf("%.5fs, length:%d\n", microtime(1)-$started_at, strlen($data));
}

echo "serialize\n";

benchmark(function() use($data){
    return serialize($data);
});


echo "json_encode\n";

benchmark(function() use($data){
    return json_encode($data);
});


echo "serialize+gzip\n";

benchmark(function() use($data){
    return gzcompress(serialize($data));
});

echo "json_encode+gzip\n";

benchmark(function() use($data){
    return gzcompress(json_encode($data));
});




f
f223156
回复 @Tuesday : 就我来讲, 我手头项目的序列化缓存基本都用memcached, 压一下内存利用率可以提高不少, 而且php的memcache库也提供setCompressThreshold方法,不需要手工干涉.
Tuesday
Tuesday
回复 @f223156 : 谢谢, 数据测试非常全面. 压缩与不带压缩, 时间花费多了一个等级, 可容量也相差大, 不知道如何选择了, 是求速度还是求容易小.
f
f223156
回复 @Tuesday : 不是顶楼那种结构单一数据, serialize占用比json_encode小, 比如这例子, 我跑下来serialize: 0.00778s, length:60983;json_encode:0.62920s, length:75707; json_encode加了JSON_UNESCAPED_UNICODE参数:0.56093s, length:67777
Tuesday
Tuesday
serialize比json快, 可容量也占用多了好几倍. 假如我只是单纯的压缩保存在文件中, 可以用json不? 不会循环1000次这样.
Tuesday
Tuesday
如雷贯耳, 你写的PHP代码真的非常有技术深度. 自叹不如. 我错了, 我不再迷恋json了.
0
Tuesday
Tuesday
<?php
@set_time_limit(0);
if(php_sapi_name()!=='cli') {
    header('Content-Type:text/plain');
}
$s = file_get_contents('http://www.oschina.net/question/998019_121505');

$data = array('data'=>str_repeat($s,100));


function benchmark($function, $times=1){
    $started_at = microtime(1);
    $data = null;
    for($i=0; $i<$times; $i++){
        $data = $function();
    }
    
    printf("%.5fs, length:%.5fm\n\n", microtime(1)-$started_at, (strlen($data) / 1024 /1024));
}


echo "serialize \n";

benchmark(function() use($data){
    $t = ((serialize($data)));
    $s = unserialize((($t)));
    return $t;
});

echo "serialize + base64 \n";

benchmark(function() use($data){
    $t = base64_encode((serialize($data)));
    $s = unserialize((base64_decode($t)));
    return $t;
});

echo "serialize + gzip \n";

benchmark(function() use($data){
    $t = (gzcompress(serialize($data)));
    $s = unserialize(gzuncompress(($t)));
    return $t;
});

echo "serialize+base64_encode +gzip \n";
benchmark(function() use($data){
    $t = base64_encode(gzcompress(serialize($data)));
    $s = unserialize(gzuncompress(base64_decode($t)));
    return $t;
});
exit();

返回值:

serialize 
0.01427s, length:6.02410m

serialize + base64 
0.17287s, length:8.03214m

serialize + gzip 
0.43907s, length:1.44310m

serialize+base64_encode +gzip 
0.51364s, length:1.92414m

感觉各有优势, 不知道选择哪种方案来做...

要么时间慢, 要么容量大, 没有即时间快,又容量小的方案

返回顶部
顶部