关于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 相关文章推荐
Content-type 的说明
Oct 09 PHP
php strcmp使用说明
Apr 22 PHP
关于shopex同步ucenter的redirect问题,导致script不运行
Apr 10 PHP
ThinkPHP中处理表单中的注意事项
Nov 22 PHP
将PHP的session数据存储到数据库中的代码实例
Jun 24 PHP
php利用header函数下载各种文件
Aug 24 PHP
thinkPHP的表达式查询用法详解
Sep 14 PHP
PHP连接MySQL进行增、删、改、查操作
Feb 19 PHP
laravel 解决路由除了根目录其他都404的问题
Oct 18 PHP
PHP实现笛卡尔积算法的实例讲解
Dec 22 PHP
Laravel框架下的Contracts契约详解
Mar 17 PHP
PHP7 新增常量
Mar 09 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
在DC的漫画和电影中,蝙蝠侠的宿敌,小丑的真名是什么?
2020/04/09 欧美动漫
第十三节--对象串行化
2006/11/16 PHP
php调用Google translate_tts api实现代码
2013/08/07 PHP
ThinkPHP实现二级循环读取的方法
2014/11/03 PHP
PHP实现的简易版图片相似度比较
2015/01/07 PHP
一张表搞清楚php is_null、empty、isset的区别
2015/07/07 PHP
ecshop添加菜单及权限分配问题
2017/11/21 PHP
javascript无刷新评论实现方法
2015/05/13 Javascript
AngularJS基础 ng-open 指令简单实例
2016/08/02 Javascript
浅析location.href跨窗口调用函数
2016/11/22 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
详解Vue整合axios的实例代码
2017/06/21 Javascript
jquery实现的简单轮播图功能【适合新手】
2018/08/17 jQuery
Nodejs libuv运行原理详解
2019/08/21 NodeJs
layui添加动态菜单与选项卡 AJAX请求的例子
2019/09/25 Javascript
深入分析在Python模块顶层运行的代码引起的一个Bug
2014/07/04 Python
利用python求相邻数的方法示例
2017/08/18 Python
Python文件如何引入?详解引入Python文件步骤
2018/12/10 Python
Python实现二叉树的常见遍历操作总结【7种方法】
2019/03/06 Python
python中break、continue 、exit() 、pass终止循环的区别详解
2019/07/08 Python
Django 通过JS实现ajax过程详解
2019/07/30 Python
使用python os模块复制文件到指定文件夹的方法
2019/08/22 Python
Python如何使用字符打印照片
2020/01/03 Python
matplotlib基础绘图命令之bar的使用方法
2020/08/13 Python
Python的logging模块基本用法
2020/12/24 Python
HTML5 FormData 方法介绍以及实现文件上传示例
2017/09/12 HTML / CSS
美国领先的汽车轮胎和轮毂供应商:TireBuyer
2016/07/21 全球购物
澳大利亚药房在线:ThePharmacy
2017/10/04 全球购物
个人简历中的自我评价范例
2013/10/29 职场文书
九年级物理教学反思
2014/01/29 职场文书
2014年机关植树节活动方案
2014/02/27 职场文书
我的中国梦演讲稿800字
2014/08/19 职场文书
乡镇镇长个人整改措施
2014/10/01 职场文书
2014年药店店长工作总结
2014/11/17 职场文书
《山中访友》教学反思
2016/02/24 职场文书
十大最强格斗系宝可梦,超梦X仅排第十,第二最重格斗礼仪
2022/03/18 日漫