duannai1883 2014-01-09 13:12
浏览 440
已采纳

如何将大对象/数组序列化为JSON

My app needs to produce json of an object that has a large data property of type array. The array needs to remain in memory as it collects DB output and some properties can only be determined once the array is completed.

Complication: the array is numerically-based and must appear as such in the json output, therefore straight json_encode() is not an option.

To make this possible on low-spec machines like RasPi I've looked into trimming memory consumption:

  1. Use SPLFixedArray
  2. Use string and pack()

Both approaches take care of the array storage memory problem but fail when it comes to encoding in JSON.

I've looked into implementing JsonSerializable but as it forces users to return the result which is then encoded in Json I'm back to

public function jsonSerialize() {
    return $this->toArray();
}

which has the same memory problems.

zendframework/Component_ZendJson looks promising as it looks for objects having a toJson() method to provide their own encoding as stringinstead of object.

I'm wondering if there are better options that don't give memory issues?

  • 写回答

2条回答

  • dql1978dql1978 2014-05-29 10:57
    关注

    In my investigation I've looked at 5 different approaches for storing large arrays of tuples in memory, summarized here with their results (sampled at 50k records):

    1. Naive

      Exporting json is straightforward with json_encode using array(array(), array())

      Memory: 18.5MB (huge)
      Time: ~100ms to build and dump the array (Windows PC)

    2. SPL Library

      This approach stores everything in nested SPLFixedArrays: SPLFixedArray[SPLFixedArray]. JSON export was done extending Zend\Json\Encoder by implementing the toJson method.

      Memory: 15.5MB (still large)
      Time: ~1.3s, x10 slower

    3. SPL Library

      Similar to 2, but instead of the inner SPLFixedArray uses packed strings from PHP's pack() function.

      Memory: 3.5MB (5 times smaller)
      Time: ~1.3s, x10 slower - apparently pack() is similarly slow as nested array.

    4. SPL Library

      Similar to 2, but instead of the inner SPLFixedArray the actual Tuples are simply written as sequential values to the root array.

      Memory: 3.25MB (again smaller)
      Time: ~0.7s, only x6 slower - do we have a winner here?

    5. pack()

      Similar to 3, but instead of the root SPLFixedArray pack everything into a single string using PHP's pack() function. This does obviously need knowledge about and a fixed, identical structure of the individual arrays.

      Memory: 1.25MB (really small - only 1/12th of original memory)
      Time: ~1.7s, x16 slower

    CONCLUSION

    While (5) offers best memory utilization it is also extremely slow. For my purposes I've settled on (4) which is about 20% of original memory consumption but- when JSON encoding is taken into account- also 5~6 times slower. An acceptable compromise.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?