您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

小小一个改动,竟能让json_decode内存节省70%?

2024/3/16 16:59:59发布15次查看
json_decode对json格式的字符串进行解码,接受一个json格式的字符串并且把它转换为php变量。但是运行json_decode可能会出现超出内存上线,这是该怎么办?
如果你用php的json_decode函数解析json串,而且json串中包含一个大量元素的数组,那你就要小心解析过程中php超出内存上限了。
笔者在开发时遇到一个json文件需要解析,该json中包含了一个由众多mac地址组成的数组,像这样:
{ "name": "mac file", "date": "2017-11-08", "maclist": [ "11-11-11-11-11-11", "22-22-22-22-22-22", ... ]}
结果json_decode过程中超出了php默认的128m内存上限。
what,超限了?!这个json文件才 10m 啊!
在大骂“这函数是不是有bug”之后,仔细推敲下,发现问题出在mac地址构成的数组上。要知道php的数组是很吃内存的。
php数组究竟多吃内存,可以做个简单的试验,向数组内放入50万个mac地址,打印内存占用量:
$a = [];for ($i = 0; $i !== 500000; $i++) { $a[] = '11-11-11-11-11-11';}echo memory_get_usage() . php_eol;
如果把这些mac地址写在一个文件里,理论上只占 9.6m 磁盘空间,但是php数组维护相同的信息,却占了 72.4m 内存 。
有办法解决json_deocde时的内存超限吗?当然,简单粗暴点的话就把内存上限调高:
ini_set('memory_limit','1024m');
虽然可行,但会引发一个问题,就是:
可能被其他语言的工程师嘲笑php占内存。
那有没有更明智的办法解决内存超限问题?
有。因为php数组占用内存很大,所以我们要避免json_decode在解码时产生巨大数组。怎么做呢?这就要从json的编码格式下手,比如可以把巨大的json数组修改成字符串:
{ "name": "mac file", "date": "2017-11-08", "maclist": "11-11-11-11-11-11,22-22-22-22-22-22,...",}
我把maclist从数组转换成以逗号分割的字符串。这样可以避免json_decde产生一个巨大无比的数组,取而代之的是一个超长的字符串。
字符串占用的内存量可比数组小多了,刚才50万个mac地址,瞬间只占9.7m的内存。修改完之后,json_decode顺利解析成功,而且解析速度更快了。
原先maclist是个数组,可以通过foreach遍历其中的元素,现在是字符串了,该怎么遍历呢?
不难,可以用strtok:
$tok = strtok($maclist, ',');while ($tok !== false) { $mac = $tok; $tok = strtok(',');}
遍历的难度没有增加多少,是吧?
你可能会问,这种方法可以对付简单的json数组,如果一个json数组的每个元素是个json对象,该怎么办?
我们可以这样构造字符串:
{ "list": '{"name":"obj1"}###{"name":"obj2"}###...'}
字符串由一个个小的json组成,它们之间用特殊的标记###分割。在解析时,根据特殊标记切分出一个个json对象,再用json_decode逐个解析:
$tok = strtok($objectlist, '###'); // 按###切割while ($tok !== false){ $objectstr = $tok; // 每切割出一个json对象就解码 $object = json_decode($objectstr, true); $tok = strtok('###');}
你也可以自创一种编码/解析这个超长字符串的方法,总之最终目标就是避免json_decode在解码过程中产生超大数组。
通过本文,你应该略到了php array吃内存的能力。把json中的数组替换成字符串表示,可以节省大量的内存。我还跑了一个对比数据,给大家参考:
解析50万个mac:
保存mac地址方式数组方式字符串方式
json文件大小 9.6m 8.6m(每个元素省了一对引号)
平均内存占用 72.4m 8.7m
平均json_decode解析时间 0.73s 0.41s
解析100万个mac:
保存mac地址方式数组方式字符串方式
json文件大小 20m 18m
平均内存占用 204.6m 54.2m
平均json_decode解析时间 1.61s 0.81s
解析200万个mac:
保存mac地址方式数组方式字符串方式
json文件大小 40m 36m
平均内存占用 409.0m 108.2m
平均json_decode解析时间 3.05s 1.53s
推荐学习:php视频教程
以上就是小小一个改动,竟能让json_decode内存节省70%?的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product