PHP处理超长数据内存限制问题

目前存在多台雷达设备,对一定区域范围进行扫描,扫描后将返回约140万个点(每个点包含4个属性)的数据。
然后雷达设备将数据拼接成以 , 分隔的字符串:"x1,y1,a1,p1,x2,y2,a2,p2......x1400000,y1400000,a1400000,p1400000"
这个字符串大小应该有几十兆、不到100兆吧。
PHP代码是这样处理的:

$num=$_POST['num'];//点的总数量
$str=$_POST['str'];//点的4个属性组成的字符串
$str_arr=expload(',',$str);//将字符串转换为数组

//将数组转换成json字符串
$point=array();
for($n=1;$n<=$num;$n++){
    $x=$str_arr[$n*4-4];
    $y=$str_arr[$n*4-3];
    $a=$str_arr[$n*4-2];
    $p=$str_arr[$n*4-1];
    $point[]=array("x"=>$x,"y"=>$y,"a"=>$a,"$p"=>$p);
}
$json_str=json_encode($point);

//将json字符串保存在```.txt```文件中
$handle=fopen("./1.txt","w");
fwrite($handle, $json_str);
fclose($handle);

//返回请求成功信息
echo "ask=1&cmd=3";
exit;

对于内存消耗我不太懂,也是第一次处理这么大的数据
当雷达传输的数据只有11W组点(约3MB数据)时,我这边才能顺利接收并且进行处理
当数据再大一点之后就提示内存限制128M
我自己去网上查了一些方法,大部分都是叫改php.ini文件中memory_limit=-1
可是改了之后仍然无法传输
目前跟雷达端商量的是他每次最多给我传10W组点,然后再多个一个参数本次传输还剩多少点,PHP接收到后作为返回值给他,他再回调继续给我发,但是这样算下来,一共要进行14~15次传输才能发完一组数据...而且可行性还不确定
请问各位大大,你们在开发中遇到这种问题是怎么处理的?
在线等。。。

阅读 5.8k
5 个回答

首先你这字符串占用内存就很大了,你再转换为数组处理占用内存会非常大的。

看你的需求,最后是转换为json存到文件,json也是字符串,为何不直接字符串处理呢。

如果是php7的话不能使用preg_replace,需要换成preg_replace_callback来处理

$str=$_POST['str'];//点的4个属性组成的字符串
$json_str = '['.substr(preg_replace('/([^,]+),([^,]+),([^,]+),([^,]+),/iU','{"x":"$1","y":"$2","a":"$3","p":"$4"},',$str.','),0,-1).']';
//将json字符串保存在```.txt```文件中
$handle=fopen("./1.txt","w");
fwrite($handle, $json_str);
fclose($handle);
ini_set('memory_limit', '500M'); //内存限制
set_time_limit(0); //执行超时,0代表无限等待

题主 gzip 开启了没? 这种纯 JSON 数据,开启了以后压缩率很高的。改大了内存限制以后,网络连接也可能会超时的。

  1. web服务器接收Body有长度限制,超长不能接收, 比如nginx-client_max_body_size

  2. web模式下采用分批传输是比较好的方案

  3. 更好的方式是用socket二进制传输, 没有web模式下的各种限制, 效率较高

内存限制开大,还有post的数据量也开大就可以了。。基本上几百兆处理起来是没问题的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题