php 移动文件-面试官问:你听说过PHP内存溢出吗?你是怎么解决的

2023-08-29 0 1,791 百度已收录


有时候我们在运行php程序的时候会发现 Fatal Error: Out of memory 这样的提示。这有可能是程序中用到了大量的变量和对象,导致分配的内存不够用。


场景

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


那么解决方案如下:

<?php

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 ”

没有相关记录!

”;

exit;

}

while(!empty($farr)){
$_sub = array_splice($farr, 010000); //每次取出$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的可用内存大小;另一方面,我们需要减少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占用的显存?

php 移动文件-面试官问:你听说过PHP内存溢出吗?你是怎么解决的

从前两个案例中,我们可以得出以下推论:

结论1、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.'
'
;
echo $m-$mm;
?>

刷新页面,我们看到第一行有256个1,第二行有0。 按理说我们已经销毁了$s,而$p只是引用了$s的变量,应该没有任何内容。 另外php 移动文件,unset($s )前后显存使用量没有变化!现在我们做下面的例子

php 移动文件-面试官问:你听说过PHP内存溢出吗?你是怎么解决的

<?php
$s=str_repeat('1',256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
$s=null//设置$s为null
$mm=memory_get_usage();
echo $p.'
'
;
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.'
'
;
echo $m-$mm;

我们使用 unset() 来销毁 $s 和 $p。 此时显存使用量相差也是272,也就是说显存也可以通过这种方式释放。

那么,通过前面的例子php 移动文件,我们可以得到另一个推论:

结论2.只有当指向该变量的所有变量(如引用变量)都被销毁时,显存才会被释放。

防止内存溢出的一些优化方案

1、尽量减少静态变量的使用,需要数据复用时可以考虑引用(&)。

2、数据库操作完成后,应立即关闭连接;

3、当对象用完时,要及时调用析构函数(__destruct())。

4.使用过的变量及时销毁(unset())

5.可以使用memory_get_usage()函数获取当前占用的显存,并根据当前使用的显存调整程序

6、unset()函数只有当变量值占用显存空间超​​过256字节时才能释放显存空间。 (由PHP内核的gc垃圾回收机制决定)。

7、只有当指向该变量的所有变量(比如引用变量)都被销毁时,显存才会被释放(PHP变量的底层实现是一个_zval_struct结构体,is_ref__gc表示引用计数 is_ref__gc表示是否是引用)。

第一篇文章:

以上就是本文的全部内容。 希望对你的学习有所帮助。 如果您觉得有用,请支持一下!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 php php 移动文件-面试官问:你听说过PHP内存溢出吗?你是怎么解决的 https://www.wkzy.net/game/175744.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务