关于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 魔术函数使用说明
May 14 PHP
php环境套包 dedeampz 伪静态设置示例
Mar 26 PHP
php获得网站访问统计信息类Compete API用法实例
Apr 02 PHP
PHP借助phpmailer发送邮件
May 11 PHP
Cygwin中安装PHP方法步骤
Jul 04 PHP
PHP常用的排序和查找算法
Aug 06 PHP
实现WordPress主题侧边栏切换功能的PHP脚本详解
Dec 14 PHP
利用ajax和PHP实现简单的流程管理
Mar 23 PHP
老生常谈php中传统验证与thinkphp框架(必看篇)
Jun 10 PHP
PHP实现根据密码长度显示安全条
Jul 04 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
Jun 13 PHP
PHP进阶学习之Geo的地图定位算法详解
Jun 19 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 autoload与spl_autoload自动加载机制的深入理解
2013/06/05 PHP
从PHP的源码中深入了解stdClass类
2014/04/18 PHP
Zend Framework 2.0事件管理器(The EventManager)入门教程
2014/08/11 PHP
实现PHP搜索加分页
2016/10/12 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
2017/10/13 PHP
详解阿里云视频直播PHP-SDK接入教程
2020/07/09 PHP
javascript删除字符串最后一个字符
2014/01/14 Javascript
基于NodeJS的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
2014/09/26 NodeJs
js与jquery实时监听输入框值的oninput与onpropertychange方法
2015/02/05 Javascript
jQuery进行组件开发完整实例
2015/12/15 Javascript
快速掌握WordPress中加载JavaScript脚本的方法
2015/12/17 Javascript
基于bootstrap实现收缩导航条
2017/03/17 Javascript
Angular组件化管理实现方法分析
2017/03/17 Javascript
关于引入vue.js 文件的知识点总结
2020/01/28 Javascript
Vue路由管理器Vue-router的使用方法详解
2020/02/05 Javascript
[01:46]新英雄登场
2019/09/10 DOTA
pyqt4教程之实现windows窗口小示例分享
2014/03/07 Python
详解使用python的logging模块在stdout输出的两种方法
2017/05/17 Python
Python基于回溯法子集树模板解决取物搭配问题实例
2017/09/02 Python
运行django项目指定IP和端口的方法
2018/05/14 Python
python如何查看微信消息撤回
2018/11/27 Python
python os.path.isfile 的使用误区详解
2019/11/29 Python
Python 实现顺序高斯消元法示例
2019/12/09 Python
xadmin使用formfield_for_dbfield函数过滤下拉表单实例
2020/04/07 Python
python 实现的IP 存活扫描脚本
2020/12/10 Python
CSS3制作气泡对话框的实例教程
2016/05/10 HTML / CSS
CSS3实现10种Loading效果
2016/07/11 HTML / CSS
英国时尚高尔夫服装购物网站:Trendy Golf
2020/01/10 全球购物
俄罗斯家居用品购物网站:Евродом
2020/11/21 全球购物
2015年青年志愿者协会工作总结
2015/04/27 职场文书
2015年公司行政后勤工作总结
2015/05/20 职场文书
婚庆主持词大全
2015/06/30 职场文书
工作自我评价范文
2019/03/21 职场文书
MySql新手入门的基本操作汇总
2021/05/13 MySQL
react合成事件与原生事件的相关理解
2021/05/13 Javascript
如何解决flex文本溢出问题小结
2022/07/15 HTML / CSS