ホームページ  >  記事  >  バックエンド開発  >  PHP メモリ オーバーフローに対する最も完全なソリューション

PHP メモリ オーバーフローに対する最も完全なソリューション

PHP中文网
PHP中文网オリジナル
2016-07-25 08:58:523059ブラウズ

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 プログラムのメモリ消費を節約するために、データを再利用する必要がある場合は、参照 (&) の使用を可能な限り減らす必要があります。もう 1 つのポイントは、データベース操作が完了したら接続を直ちに閉じる必要があり、オブジェクトが使用された後はすぐにデストラクター (__destruct()) を呼び出す必要があることです。

Ⅱ。 unset の変数の破棄とメモリの解放の問題
PHP の unset() 関数は、変数をクリアして破棄するために使用されます。 unset() を使用して、未使用の変数を破棄できます。ただし、unset() を使用しても、変数が占有しているメモリを破壊できない場合があります。まず例を見てみましょう:

次のようにコードをコピーします:

<?php
$s=str_repeat(&#39;1&#39;,255); //产生由255个1组成的字符串
$m=memory_get_usage(); //获取当前占用内存
unset($s);
$mm=memory_get_usage(); //unset()后再查看当前占用内存
echo $m-$mm;
?>

最後に、unset() の前に占有されていたメモリから unset() の後に占有されていたメモリを引いた値を出力します。これが正の数の場合は、unset($) を意味します。 s) は、$s をメモリ内の Destroyed から変更しました (つまり、unset() の後にメモリ使用量が削減されました) が、PHP5 および Windows プラットフォームでは、得られた結果は 0 です。これは、unset($s) は変数 $s が占有するメモリを破壊しないことを意味しますか?もう一度次の例を作成してみましょう:

次のようにコードをコピーします:

<?php
$s=str_repeat(&#39;1&#39;,256); //产生由256个1组成的字符串
$m=memory_get_usage(); //获取当前占用内存
unset($s);
$mm=memory_get_usage(); //unset()后再查看当前占用内存
echo $m-$mm;
?>

この例は上記の例とほぼ同じですが、唯一の違いは、$s が 256 個の 1 で構成されており、最初の例より 1 つ多いことです。 1. 結果は 272 です。これは、unset($s) が $s によって占有されていたメモリを破壊したことを意味しますか?
上記 2 つの例を通じて、次の結論を導き出すことができます:
結論 1. unset() 関数は、変数値が 256 バイトを超えるメモリ空間を占有している場合にのみメモリ空間を解放できます。
では、変数値が 256 を超える限り、unset を使用するとメモリ領域を解放できますか?別の例でテストしてみましょう:

次のようにコードをコピーします:

<?php
$s=str_repeat(&#39;1&#39;,256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
unset($s); //销毁$s
$mm=memory_get_usage();
echo $p.&#39;<br />&#39;;
echo $m-$mm;
?>

ページを更新すると、最初の行には 256 個の 1 があり、2 行目は 0 であることがわかります。$s を破棄したのは当然です。また、$p は $s の変数を参照するだけであり、内容はありません。また、メモリ使用量は unset($s) の前後で変わりません。次の例を実行してみましょう:

次のようにコードをコピーします:

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

ここでページを更新すると、出力 $p には内容がなく、unset() の前後のメモリ使用量の差が 272 であることがわかります。つまり、変数によって占有されていたメモリがクリアされます。この例の $s=null は、次のように unset() で置き換えることもできます:

次のようにコードをコピーします:

<?php
$s=str_repeat(&#39;1&#39;,256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
unset($s); //销毁$s
unset($p);
$mm=memory_get_usage();
echo $p.&#39;<br />&#39;;
echo $m-$mm;
?>

unset() を使用して $s と $p の両方を破棄し、メモリ使用量 差も 272 であり、これによってメモリも解放できることがわかります。次に、別の結論を得ることができます:
結論 2. メモリは、その変数を指すすべての変数 (参照変数など) が破棄された場合にのみ解放されます。

上記は、PHP メモリ オーバーフローに対する最も完全な解決策です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。