1. 메모리 오버플로 해결 방법
데이터 통계 분석을 하다 보면 대용량 배열이 자주 발생하고, 메모리 오버플로가 발생할 수 있습니다. 이에 대한 해결 방법을 공유하겠습니다. 이 문제를 설명하기 위해 다음과 같은 예를 사용하겠습니다.
로그에 저장된 레코드 수가 500,000개라고 가정하면 해결 방법은 다음과 같습니다.
다음과 같이 코드를 복사합니다.
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의 사용 가능한 메모리 크기를 늘려야 한다는 것을 어렵지 않게 볼 수 있습니다. 다른 한편으로는 배열을 처리하는 방법을 찾는 것입니다. 일괄적으로 사용된 변수를 분할 및 정복하고 파기(설정 해제)하는 경우 일반적으로 오버플로 문제가 발생하지 않습니다.
또한, PHP 프로그램 메모리 소모를 줄이기 위해서는 정적 변수의 사용을 최대한 줄여야 하며, 데이터 재사용이 필요한 경우에는 참조(&) 사용을 고려해 볼 수 있습니다. 또 다른 요점은 데이터베이스 작업이 완료된 후 개체가 사용된 후 즉시 연결을 닫아야 하며 소멸자(__destruct())를 즉시 호출해야 한다는 것입니다.
2. 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가 구성된다는 점입니다. of 256 1로 구성됩니다. 즉, 첫 번째 예보다 1이 하나 더 많아 결과는 272입니다. 이는 unset($s)이 $s가 차지하는 메모리를 파괴했다는 의미입니까?
위의 두 가지 예를 통해 다음과 같은 결론을 내릴 수 있습니다.
결론 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.'<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로, 이 역시 메모리를 해제할 수 있음을 나타냅니다. 그러면 또 다른 결론을 얻을 수 있습니다:
결론 2. 해당 변수를 가리키는 모든 변수(참조 변수 등)가 소멸되어야 메모리가 해제됩니다.
위 내용은 PHP 메모리 오버플로에 대한 가장 완벽한 솔루션입니다. 더 많은 관련 내용을 보려면 PHP 중국어 웹사이트(www.php.cn)를 주목하세요!