关于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 相关文章推荐
Codeigniter实现智能裁剪图片的方法
Jun 12 PHP
PHP读取RSS(Feed)简单实例
Jun 12 PHP
PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
Jul 28 PHP
php中的动态调用实例分析
Jan 07 PHP
php中文繁体和简体相互转换的方法
Mar 21 PHP
php简单实现快速排序的方法
Apr 04 PHP
php检查函数必传参数是否存在的实例详解
Aug 28 PHP
thinkphp 抓取网站的内容并且保存到本地的实例详解
Aug 25 PHP
tp框架(thinkPHP)实现三次登陆密码错误之后锁定账号功能示例
May 24 PHP
php微信公众号开发之秒杀
Oct 20 PHP
PHP get_html_translation_table()函数用法讲解
Feb 16 PHP
php屏蔽错误及提示的方法
May 10 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
php部分常见问题总结
2008/03/27 PHP
Linux下 php5 MySQL5 Apache2 phpMyAdmin ZendOptimizer安装与配置[图文]
2008/11/18 PHP
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
使用php实现截取指定长度
2013/08/06 PHP
PHP实现多文件上传的方法
2015/07/08 PHP
PHP7.0版本备注
2015/07/23 PHP
PHP获取日期对应星期、一周日期、星期开始与结束日期的方法
2018/06/22 PHP
比较详细的关于javascript中void(0)的具体含义解释
2007/08/02 Javascript
JavaScript中提前声明变量或函数例子
2014/11/12 Javascript
javascript常用的方法整理
2015/08/20 Javascript
jQuery实现图片加载完成后改变图片大小的方法
2016/03/29 Javascript
jQuery组件easyui基本布局实现代码
2016/08/25 Javascript
分享5个顶级的JavaScript Ajax组件库
2018/09/16 Javascript
微信小程序实现留言板功能
2018/11/02 Javascript
JavaScript查看代码运行效率console.time()与console.timeEnd()用法
2019/01/18 Javascript
微信小程序实现上传word、txt、Excel、PPT等文件功能
2019/05/23 Javascript
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
jQuery实现鼠标放置名字上显示详细内容气泡提示框效果的方法分析
2020/04/04 jQuery
[01:10:58]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
python爬取拉勾网职位数据的方法
2018/01/24 Python
使用python opencv对目录下图片进行去重的方法
2019/01/12 Python
python全栈知识点总结
2019/07/01 Python
python按比例随机切分数据的实现
2019/07/11 Python
印度在线内衣和时尚目的地:Zivame
2017/09/28 全球购物
早餐连锁店计划书
2014/01/08 职场文书
幼儿园数学教学反思
2014/02/02 职场文书
上课玩手机检讨书
2014/02/08 职场文书
优秀党支部书记事迹材料
2014/05/29 职场文书
幼儿教师暑期培训方案
2014/08/27 职场文书
爱祖国爱家乡演讲稿
2014/09/02 职场文书
2015年元旦标语大全
2014/12/09 职场文书
部队2015年终工作总结
2015/04/02 职场文书
2015年教务处干事工作总结
2015/07/22 职场文书
电力安全教育培训心得体会
2016/01/11 职场文书
MySQL 使用自定义变量进行查询优化
2021/05/14 MySQL
25张裸眼3D图片,带你重温童年的记忆,感受3D的魅力
2022/02/06 杂记