我的应用程序需要生成一个对象的json,该对象具有类型为array的大data
属性。数组需要在收集数据库输出时保留在内存中,并且只有在数组完成后才能确定某些属性。
复杂化:数组是基于数字的,并且必须在json输出中显示,因此直接json_encode()
不是一个选项。
为了在像RasPi这样的低规格机器上实现这一点,我研究了修剪内存消耗:
SPLFixedArray
string
和pack()
这两种方法都会处理数组存储内存问题,但在使用JSON进行编码时会失败。
我已经研究过实现JsonSerializable
但是因为它迫使用户返回结果,然后在Json中编码我回到
public function jsonSerialize() {
return $this->toArray();
}
具有相同的内存问题。
zendframework/Component_ZendJson
看起来很有前途,因为它会查找具有toJson()
方法的对象,以便将自己的编码提供为string
而不是object
。
我想知道是否有更好的选项不会给出内存问题?
答案 0 :(得分:5)
在我的调查中,我研究了5种不同的方法,用于在内存中存储大量元组,在此总结其结果(以50k记录采样):
幼稚
json_encode使用array(array(), array())
内存:18.5MB(巨大)
时间:〜100ms构建和转储阵列(Windows PC)
SPL资料库
此方法将所有内容存储在嵌套SPLFixedArrays
:SPLFixedArray[SPLFixedArray]
中。通过实施Zend\Json\Encoder
方法,JSON导出扩展了toJson
。
内存:15.5MB(仍然很大)
时间:~1.3s,x10慢
SPL图书馆
与2类似,但不是内部SPLFixedArray
使用来自PHP的pack()
函数的压缩字符串。
内存:3.5MB(小5倍)
时间:~1.3s,x10较慢 - 显然pack()
与嵌套数组一样慢。
SPL图书馆
与2类似,但不是内部SPLFixedArray
,而是将实际元组简单地写为根数组的顺序值。
内存:3.25MB(再次更小)
时间:约0.7秒,只有x6慢 - 我们在这里有赢家吗?
pack()
与3类似,但使用PHP的SPLFixedArray
函数将所有内容打包到单个字符串中,而不是根pack()
。这显然需要了解各个阵列的固定,相同结构。
内存:1.25MB(非常小 - 仅为原始内存的1/12 )
时间:~1.7s,x16慢
结论
虽然(5)提供了最佳的内存利用率,但它也非常慢。出于我的目的,我已经确定了(4)这约占原始内存消耗的20%但是 - 当考虑JSON编码时 - 也慢了5~6倍。可接受的妥协。
答案 1 :(得分:-1)
根据json.org:
JSON基于两种结构:
- 名称/值对的集合。在各种语言中,这被实现为对象,记录,结构,字典,哈希表,键控 列表或关联数组。
- 有序的值列表。在大多数语言中,这被实现为数组,向量,列表或序列。
我不知道是否存在内存问题,但请考虑以下代码:
<?php
// No declared index causes no index in JSON
$arr = array('dssdf','38904uj');
echo json_encode($arr).'<br><br>';
// ["dssdf","38904uj"]
// start array at 0 removes the index from JSON
$arr = array('0'=>'dssdf','1'=>'38904uj');
echo json_encode($arr).'<br><br>';
// ["dssdf","38904uj"]
// start array at 1 forces the index to show in JSON
$arr = array('1'=>'dssdf','2'=>'38904uj');
echo json_encode($arr).'<br><br>';
// {"1":"dssdf","2":"38904uj"}
// skip an index forces the index to show in JSON
$arr = array('0'=>'dssdf','1'=>'38904uj','3'=>'321as5d4');
echo json_encode($arr).'<br><br>';
// {"0":"dssdf","1":"38904uj","3":"321as5d4"}
// JSON_FORCE_OBJECT option forces indexes
$arr = array('0'=>'dssdf','1'=>'38904uj');
echo json_encode($arr, JSON_FORCE_OBJECT).'<br><br>';
// {"0":"dssdf","1":"38904uj"}
?>