我需要在平面文件中存储多维数据关联数组,以便进行缓存。我可能偶尔会遇到需要将其转换为JSON以在我的web应用程序中使用,但绝大多数情况下,我将直接在PHP中使用数组。

在这个文本文件中将数组存储为JSON还是PHP序列化数组更有效?我查看了一下,似乎在最新版本的PHP(5.3)中,json_decode实际上比反序列化更快。

我目前倾向于将数组存储为JSON,因为我觉得如果有必要的话,它更容易被人阅读,它可以在PHP和JavaScript中使用,而且从我所读到的,它甚至可能更快地解码(虽然不确定编码)。

有人知道有什么陷阱吗?有人有好的基准来显示这两种方法的性能优势吗?


当前回答

Y刚刚测试了serialized和json的encode和decode,加上它将把字符串存储的大小。

JSON encoded in 0.067085981369 seconds. Size (1277772)
PHP serialized in 0.12110209465 seconds. Size (1955548)
JSON decode in 0.22470498085 seconds
PHP serialized in 0.211947917938 seconds
json_encode() was roughly 80.52% faster than serialize()
unserialize() was roughly 6.02% faster than json_decode()
JSON string was roughly 53.04% smaller than Serialized string

我们可以得出结论,JSON编码更快,结果字符串更小,但unserialize解码字符串更快。

其他回答

真是个不错的话题,在看了几个答案后,我想分享我在这个问题上的实验。

我有一个用例,几乎每次与数据库对话时都需要查询一些“巨大的”表(不要问为什么,只是一个事实)。数据库缓存系统是不合适的,因为它不会缓存不同的请求,所以我想到了php缓存系统。

我尝试了apcu,但它不符合需求,内存在这种情况下不够可靠。下一步是通过序列化将缓存到文件中。

表有14355个条目,有18列,这些是我的测试和读取序列化缓存的统计:

JSON:

正如大家所说,json_encode/json_decode的主要不便之处在于它将所有内容转换为StdClass实例(或对象)。如果你需要循环它,你可能会把它转换成一个数组,是的,这会增加转换时间

平均时间:780.2 ms;内存使用:41.5MB;缓存文件大小:3.8MB

Msgpack

@hutch提到了msgpack。漂亮的网站。让我们试一试,好吗?

平均时间:497 ms;内存使用:32MB;缓存文件大小:2.8MB

这样好多了,但需要一个新的扩展;编译有时害怕的人…

IgBinary

@GingerDog提到了igbinary。注意,我设置了igbinary.compact_strings= off,因为我更关心读取性能而不是文件大小。

平均时间:411.4 ms;内存使用:36.75MB;缓存文件大小:3.3MB

比味精包装好。不过,这个也需要编译。

系列化/非系列化

平均时间:477.2 ms;内存使用:36.25MB;缓存文件大小:5.9MB

比JSON更好的性能,数组越大,json_decode就越慢,但你已经知道了。

这些外部扩展缩小了文件大小,在纸上看起来很棒。数字不会说谎。如果您得到的结果与使用标准PHP函数得到的结果几乎相同,那么编译扩展还有什么意义呢?

我们还可以推断出,根据你的需求,你会选择与别人不同的东西:

IgBinary真的很好,比MsgPack执行得更好 Msgpack更擅长压缩数据(注意,我没有尝试igbinary 紧凑。字符串选项)。 不想编译?使用标准。

就是这样,另一个序列化方法的比较,帮助您选择一个!

*使用PHPUnit 3.7.31测试,php 5.5.10 -仅使用标准硬盘和旧双核CPU解码- 10个相同用例测试的平均数字,您的统计数据可能不同

如果您想在不同的机器上或通过FTP备份数据和恢复数据,JSON更好。

例如,serialize如果你在Windows服务器上存储数据,通过FTP下载并将其恢复到Linux服务器上,由于字符重新编码,它不能再工作了,因为serialize存储字符串的长度,并且在Unicode > UTF-8转码中,一些1字节的字符可能会变成2字节长,使算法崩溃。

仅供参考——如果您想将数据序列化为易于阅读和理解的JSON,但具有更多的压缩和更高的性能,您应该检查messagpack。

如果总结一下人们在这里所说的话,json_decode/encode似乎比序列化/反序列化BUT更快 如果执行var_dump,序列化对象的类型将被更改。 如果出于某种原因想要保留类型,请使用serialize!

(例如stdClass vs array)

序列化/非系列化:

Array cache:
array (size=2)
  'a' => string '1' (length=1)
  'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(Controller\Test)[8]
  protected 'view' => 

JSON 编码/解码

Array cache:
object(stdClass)[7]
  public 'a' => string '1' (length=1)
  public 'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(stdClass)[8]

正如你所看到的json_encode/decode将所有转换为stdClass,这不是很好,对象信息丢失…所以根据需要来决定,特别是如果它不仅仅是数组……

在你做出最终决定之前,请注意JSON格式对于关联数组是不安全的——json_decode()将它们作为对象返回:

$config = array(
    'Frodo'   => 'hobbit',
    'Gimli'   => 'dwarf',
    'Gandalf' => 'wizard',
    );
print_r($config);
print_r(json_decode(json_encode($config)));

输出是:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)