我需要在平面文件中存储多维关联数据数组以用于缓存目的 . 我偶尔会遇到将其转换为JSON以便在我的Web应用程序中使用的需要,但绝大多数时候我将直接在PHP中使用该数组 .
将数组存储为此文本文件中的JSON或PHP序列化数组会更高效吗?我环顾四周,似乎在最新版本的PHP(5.3)中, json_decode
实际上比 unserialize
更快 .
我目前倾向于将数组存储为JSON,因为我觉得如果有必要,它可以更容易被人阅读,它可以在PHP和JavaScript中使用,只需要很少的努力,从我读过的,它甚至可能是更快解码(不确定编码) .
有谁知道任何陷阱?任何人都有良好的基准来展示这两种方法的性能优势?
19 回答
THX - 用于此基准代码:
我用于配置的数组的结果是休闲:JSON编码为0.0031511783599854秒
PHP序列化为0.0037961006164551秒
json_encode()
比在0.0070841312408447秒内编码的serialize()
JSON快约20.47%PHP序列化为0.0035839080810547秒
unserialize()
比json_encode()
快大约97.66%所以 - 在你自己的数据上测试它 .
我增加了测试以包括反序列化性能 . 这是我得到的数字 .
所以json似乎更快编码,但解码速度慢 . 因此,它可能取决于您的应用程序以及您期望做的最多 .
我写了一篇关于这个主题的博文:“Cache a large array: JSON, serialize or var_export?” . 在这篇文章中,显示serialize是小型到大型阵列的最佳选择 . 对于非常大的阵列(> 70MB),JSON是更好的选择 .
似乎序列化是我将要使用的原因有两个:
有人指出,unserialize比json_decode更快,并且'read'情况听起来比'write'情况更可能 .
我在使用UTF-8字符无效的字符串时遇到了json_encode问题 . 当发生这种情况时,字符串最终变为空,从而导致信息丢失 .
如果要备份数据并在其他计算机上或通过FTP还原数据,JSON会更好 .
例如,如果您将数据存储在Windows服务器上进行序列化,则通过FTP下载并在Linux上恢复它由于字符串重新编码而无法再工作,因为serialize存储字符串的长度和Unicode > UTF-8转码大约1个字节的字符串可能会变成2个字节长,导致算法崩溃 .
如果您要缓存最终需要"include"的信息,可能需要尝试使用var_export . 这样你只能在"serialize"中获取,而不是在_166779中 .
在这里查看结果(抱歉将PHP代码放入JS代码框中):
http://jsfiddle.net/newms87/h3b0a0ha/embedded/result/
RESULTS: serialize() and unserialize() are both significantly faster in PHP 5.4 on arrays of varying size.
我在真实世界数据上制作了一个测试脚本,用于比较json_encode vs serialize和json_decode vs unserialize . 测试在 生产环境 电子商务站点的缓存系统上运行 . 它只是将数据放在缓存中,并测试编码/解码(或序列化/反序列化)所有数据的时间,并将其放在一个易于查看的表中 .
我在PHP 5.4共享托管服务器上运行它 .
结果是非常确定的,对于这些从大到小的数据集,序列化和反序列化是明显的赢家 . 特别是对于我的用例,json_decode和unserialize对于缓存系统来说是最重要的 . Unserialize在这里几乎是无处不在的赢家 . 它通常是json_decode的2到4倍(有时是6或7倍) .
值得注意的是,@ peter-bailey的结果存在差异 .
以下是用于生成结果的PHP代码:
首先,我更改了脚本以进行更多基准测试(并且还执行1000次运行而不是仅运行1次):
我使用了PHP 7的这个版本:
我的结果是:
所以 clearly ,serialize / unserialize是 fastest 方法,而json_encode / decode是 most portable.
如果您考虑的情况是您读取/写入序列化数据的频率超过了您需要发送到非PHP系统或从非PHP系统接收的10倍或更多,那么最好使用序列化/反序列化并在序列化之前使用json_encode或json_decode在时间方面 .
我建议你使用Super Cache,这是一个不使用
json_encode
或serialize
的文件缓存机制 . 与其他PHP Cache机制相比,它使用简单,速度非常快 .https://packagist.org/packages/smart-php/super-cache
例如:
只是一个假设 - 如果你想将你的数据序列化为易于阅读和理解的东西,如JSON,但压缩率更高,性能更高,你应该看看messagepack.
您可能也对https://github.com/phadej/igbinary感兴趣 - 它为PHP提供了不同的序列化'engine' .
我在64位平台上使用PHP 5.3.5的随机/随意“性能”数据显示:
JSON:
JSON编码在2.180496931076秒
JSON在9.8368630409241秒内解码
序列化"String"大小:13993
原生PHP:
PHP序列化为2.9125759601593秒
PHP在6.4348418712616秒中未序列化
序列化"String"大小:20769
Igbinary:
WIN igbinary序列化为1.6099879741669秒
WIN igbinrary在4.7737920284271秒中反序列化
WIN序列化"String"大小:4467
因此,igbinary_serialize()和igbinary_unserialize()更快,并且使用更少的磁盘空间 .
我使用了如上所述的fillArray(0,3)代码,但使数组键的字符串更长 .
igbinary可以存储与PHP的本机序列化相同的数据类型(因此对象等没有问题),如果您愿意,可以告诉PHP5.3使用它进行会话处理 .
另见http://ilia.ws/files/zendcon_2010_hidden_features.pdf - 特别是幻灯片14/15/16
在做出最终决定之前,请注意JSON格式对于关联数组是不安全的 -
json_decode()
会将它们作为对象返回:输出是:
取决于您的优先事项 .
如果性能是您的绝对驾驶特性,那么一定要使用最快的一个 . 在做出选择之前,请确保您已充分了解差异
与
serialize()
不同,您需要添加额外参数以保持UTF-8字符不变:json_encode($array, JSON_UNESCAPED_UNICODE)
(否则它将UTF-8字符转换为Unicode转义序列) .JSON将无法记录对象的原始类(它们始终是恢复为stdClass的实例) .
您无法利用
__sleep()
和__wakeup()
与JSON默认情况下,仅使用JSON序列化公共属性 . (在
PHP>=5.4
中,您可以实现JsonSerializable来更改此行为) .JSON更具可移植性
而且可能还有一些我目前无法想到的其他差异 .
一个简单的速度测试来比较两者
我也做了一个小基准 . 我的结果是一样的 . 但我需要解码性能 . 在我注意到的地方,就像上面提到的一些人一样,
unserialize
比json_decode
快 .unserialize
大约占json_decode
时间的60-70% . 所以结论很简单:当您需要编码性能时,使用json_encode
,当您在解码时需要性能时,请使用unserialize
. 因为您无法合并这两个函数,所以您需要在需要更高性能的地方进行选择 .我的伪基准:
使用一些随机键和值定义数组$ arr
for x <100; X ; serialize和json_encode $ arr的array_rand
,y <1000; y; json_decode json编码的字符串 - 计算时间
,y <1000; y;反序列化序列化字符串 - 计算时间
回显更快的结果
在avarage上:unserialize在json_decode的4倍上赢了96次 . 超过2.5毫秒的平均大约1.5毫秒 .
JSON 比PHP的序列化格式更简单,更快,应该使用 unless :
您正在存储深层嵌套数组:json_decode():"This function will return false if the JSON encoded data is deeper than 127 elements."
您将需要反序列化的对象存储为正确的类
你're interacting with old PHP versions that don' t支持json_decode
Y刚测试了序列化和json编码和解码,加上存储字符串的大小 .
我们可以得出结论,JSON编码速度更快,结果更小,但是反序列化对字符串的解码速度更快 .
非常好的主题,在阅读了几个答案后,我想分享我在这个主题上的实验 .
我有一个用例,几乎每次我与数据库交谈时都需要查询一些“巨大的”表(不要问为什么,只是一个事实) . 数据库缓存系统不合适,因为它不会缓存不同的请求,所以我关于php缓存系统 .
我试过
apcu
但在这种情况下它没有足够的可靠性 . 下一步是使用序列化缓存到文件中 .Table有14355个条目,有18列,这些是我在读取序列化缓存时的测试和统计信息:
JSON:
正如大家所说,
json_encode
/json_decode
的主要不便之处在于它将所有内容转换为StdClass
实例(或对象) . 如果你需要循环它,将它转换为数组是你增加转换时间的原因Msgpack
@hutch提及msgpack . 漂亮的网站 . 我们试一试吧?
那更好,但需要新的扩展;编译有时害怕人...
IgBinary
@GingerDog提到igbinary . 请注意,我已经设置了
igbinary.compact_strings=Off
因为我更关心阅读表演而不是文件大小 .比msg包更好 . 不过,这个还需要编译 .
序列化/反序列化
比JSON更好的性能,阵列越大,速度越慢
json_decode
,但你已经是新的了 .这些外部扩展正在缩小文件大小,在纸面上看起来很棒 . 数字不在于* . 如果您获得与标准PHP函数几乎相同的结果,那么编译扩展的重点是什么?
我们还可以推断,根据您的需要,您将选择与其他人不同的东西:
IgBinary非常好,性能比MsgPack好
Msgpack更适合压缩数据(请注意,我没有尝试过igbinary compact.string选项) .
不想编译?使用标准 .
就是这样,另一个序列化方法比较,以帮助您选择一个!
*使用PHPUnit 3.7.31,php 5.5.10进行测试 - 仅使用标准hardrive和旧的双核CPU解码 - 在10个相同的用例测试中的平均数字,您的统计数据可能会有所不同
我已经在一个相当复杂,温和嵌套的多哈希中对其进行了彻底的测试,其中包含各种数据(字符串,NULL,整数),并且序列化/非序列化的结果比json_encode / json_decode快得多 .
json在我的测试中唯一的优势是它的尺寸更小 .
这些是在PHP 5.3.3下完成的,如果您需要更多详细信息,请与我们联系 .
以下是测试结果,然后是生成它们的代码 . 我无法提供测试数据,因为它会显示我不能放弃的信息 .
如果总结一下人们在这里说的话,json_decode / encode似乎比序列化/反序列化更快但是如果你做了var_dump,那么序列化对象的类型就会改变 . 如果由于某种原因你想保留类型,请使用序列化!
(例如尝试stdClass vs array)
序列化/反序列化:
json编码/解码
正如你所看到的,json_encode / decode将所有转换为stdClass,这不是那么好,对象信息丢失......所以根据需要决定,特别是如果它不仅仅是数组......