关于PHP内存溢出问题的解决方法


Posted in PHP onJune 25, 2013

一.内存溢出解决方案
在做数据统计分析时,经常会遇到大数组,可能会发生内存溢出,这里分享一下我的解决方案。还是用例子来说明这个问题,如下:
假定日志中存放的记录数为500000条,那么解决方案如下:

ini_set(‘memory_limit','64M'); //重置php可以使用的内存大小为64M,一般在远程主机上是不能修改php.ini文件的,只能通过程序设置。注:在safe_mode(安全模式)下,ini_set失效
set_time_limit(600);//设置超时限制为6分钟
$farr = $Uarr = $Marr = $IParr = $data = $_sub = array();
$spt = ”$@#!$”;
$root = ”/Data/webapps/VisitLog”;
$path = $dpath = $fpath = NULL;
$path = $root.”/”.date(“Y-m”,$timestamp);
$dpath = $path.”/”.date(“m-d”,$timestamp);
for($j=0;$j<24;$j++){
$v = ($j < 10) ? ”0″.$j : $j;
$gpath = $dpath.”/”.$v.”.php”;
if(!file_exists($gpath)){
continue;
} else {
$arr = file($gpath);////将文件读入数组中
array_shift($arr);//移出第一个单元-》<?php exit;?>
$farr = array_merge($farr,$arr);
unset($arr);
}
}
if(empty($this->farr)){
echo ”<p><center>没有相关记录!</center></p>”;
exit;
}
while(!empty($farr)){
$_sub = array_splice($farr, 0, 10000); //每次取出$farr中1000个
for($i=0,$scount=count($_sub);$i<$scount;$i++){
$arr = explode($spt,$_sub[$i]);
$Uarr[] = $arr[1]; //vurl
$Marr[] = $arr[2]; //vmark
$IParr[] = $arr[3].” |$nbsp;”.$arr[1]; //IP
}
unset($_sub);//用完及时销毁
}
unset($farr);

这里,不难看出,一方面,我们要增加PHP可用内存大小,另一方面,只要我们想办法对数组进行分批处理,分而治之,将用过的变量及时销毁(unset),一般是不会出现溢出问题的。

另外,为了节省PHP程序内存损耗,我们应当尽可能减少静态变量的使用,在需要数据重用时,可以考虑使用引用(&)。再一点就是:数据库操作完成后,要马上关闭连接;一个对象使用完,要及时调用析构函数(__destruct())。

二.unset销毁变量并释放内存问题
PHP的unset()函数用来清除、销毁变量,不用的变量,我们可以用unset()将它销毁。但是某些时候,用unset()却无法达到销毁变 量占用的内存!我们先看一个例子:

<?php
$s=str_repeat('1',255); //产生由255个1组成的字符串
$m=memory_get_usage(); //获取当前占用内存
unset($s);
$mm=memory_get_usage(); //unset()后再查看当前占用内存
echo $m-$mm;
?>

最后输出unset()之前占用内存减去unset()之后占用内存,如果是正数,那么说明unset($s)已经将$s从内存中销毁(或者说,unset()之后内存占用减少了),可是我在PHP5和windows平台下,得到的结果是:0。这是否可以说明,unset($s)并没有起 到销毁变量$s所占用内存的作用呢?我们再作下面的例子:
<?php
$s=str_repeat('1',256); //产生由256个1组成的字符串
$m=memory_get_usage(); //获取当前占用内存
unset($s);
$mm=memory_get_usage(); //unset()后再查看当前占用内存
echo $m-$mm;
?>

这个例子,和上面的例子几乎相同,唯一的不同是,$s由256个1组成,即比第一个例子多了一个1,得到结果是:272。这是否可以说 明,unset($s)已经将$s所占用的内存销毁了?
通过上面两个例子,我们可以得出以下结论:
结论一、unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间。
那么是不是只要变量值超过256,使用unset就可以释放内存空间呢?我们再通过一个例子来测试一下:
<?php
$s=str_repeat('1',256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
unset($s); //销毁$s
$mm=memory_get_usage();
echo $p.'<br />';
echo $m-$mm;
?>

刷新页面,我们看到第一行有256个1,第二行是0,按理说我们已经销毁了$s,而$p只是引用$s的变量,应该是没有内容了,另 外,unset($s)前后内存占用没变化!现在我们再做以下的例子:
<?php
$s=str_repeat('1',256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
$s=null; //设置$s为null
$mm=memory_get_usage();
echo $p.'<br />';
echo $m-$mm;
?>

现在刷新页面,我们看到,输出$p已经是没有内容了,unset()前后内存占用量之差是272,即已经清除了变量占用的内存。本例中的$s=null也 可以换成unset(),如下:
<?php
$s=str_repeat('1',256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
unset($s); //销毁$s
unset($p);
$mm=memory_get_usage();
echo $p.'<br />';
echo $m-$mm;
?>

我们将$s和$p都使用unset()销毁,这时再看内存占用量之差也是272,说明这样也可以释放内存。那么,我们可以得到另外一条结论:
结论二、只有当指向该变量的所有变量(如引用变量)都被销毁后,才会释放内存。
PHP 相关文章推荐
使用PHP数组实现无限分类,不使用数据库,不使用递归.
Dec 09 PHP
php调用mysql存储过程
Feb 14 PHP
一个PHP数组应该有多大的分析
Jul 30 PHP
PHP中利用substr_replace将指定两位置之间的字符替换为*号
Jan 27 PHP
解析CodeIgniter自定义配置文件
Jun 18 PHP
php的sprintf函数的用法 控制浮点数格式
Feb 14 PHP
百度地图经纬度转换到腾讯地图/Google 对应的经纬度
Aug 28 PHP
php array_values 返回数组的所有值详解及实例
Nov 12 PHP
PHP巧妙利用位运算实现网站权限管理的方法
Mar 12 PHP
php中通用的excel导出方法实例
Dec 30 PHP
PHP智能识别收货地址信息实例
Jan 05 PHP
PHP常见字符串操作函数与用法总结
Mar 04 PHP
关于PHP session 存储方式的详细介绍
Jun 25 #PHP
基于php使用memcache存储session的详解
Jun 25 #PHP
解析Extjs与php数据交互(增删查改)
Jun 25 #PHP
深入extjs与php参数交互的详解
Jun 25 #PHP
解析centos中Apache、php、mysql 默认安装路径
Jun 25 #PHP
关于js与php互相传值的介绍
Jun 25 #PHP
探讨:如何使用PhpDocumentor生成文档
Jun 25 #PHP
You might like
xml在joomla表单中的应用详解分享
2012/07/19 PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
2016/02/26 PHP
Javascript实现DIV滚动自动滚动到底部的代码
2012/03/01 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
jQuery打字效果实现方法(附demo源码下载)
2015/12/18 Javascript
Jquery Easyui日历组件Calender使用详解(23)
2016/12/18 Javascript
vue侧边栏动态生成下级菜单的方法
2018/09/07 Javascript
Bootstrap Paginator+PageHelper实现分页效果
2018/12/29 Javascript
构建大型 Vue.js 项目的10条建议(小结)
2019/11/14 Javascript
微信小程序动态设置图片大小的方法
2019/11/21 Javascript
Vue+Node实现的商城用户管理功能示例
2019/12/23 Javascript
vue项目在webpack2实现移动端字体自适配功能
2020/06/02 Javascript
使用Python编写一个在Linux下实现截图分享的脚本的教程
2015/04/24 Python
python简单实现基于SSL的IRC bot实例
2015/06/15 Python
Python栈算法的实现与简单应用示例
2017/11/01 Python
python实现微信小程序自动回复
2018/09/10 Python
Tensorflow实现多GPU并行方式
2020/02/03 Python
opencv 查找连通区域 最大面积实例
2020/06/04 Python
基于python判断字符串括号是否闭合{}[]()
2020/09/21 Python
Python plt 利用subplot 实现在一张画布同时画多张图
2021/02/26 Python
网页布局中CSS样式无效的十个重要原因详解
2017/08/10 HTML / CSS
数据库基础的一些面试题
2012/02/25 面试题
ShellScript面试题一则-ShellScript编程
2014/06/24 面试题
Servlet面试题库
2015/07/18 面试题
医学生个人求职信范文
2014/02/07 职场文书
社区平安建设方案
2014/05/25 职场文书
伦敦奥运会的口号
2014/06/21 职场文书
2014入党积极分子破除“四风”思想汇报
2014/09/14 职场文书
大学生第一学年自我鉴定2015
2014/09/28 职场文书
2014年商场工作总结
2014/11/22 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
《怀念母亲》教学反思
2016/02/19 职场文书
如何制定一份可行的计划!
2019/06/21 职场文书
加薪申请书应该这样写!
2019/07/04 职场文书
原生Javascript+HTML5一步步实现拖拽排序
2021/06/12 Javascript
JS数组方法some、every和find的使用详情
2021/10/05 Javascript