PHPメモリオーバーフローソリューション
3810 ワード
一.メモリオーバーフロー解決方案
データ統計分析では、大きな配列に遭遇することが多く、メモリオーバーフローが発生する可能性があります.ここで私のソリューションを共有します.やはり例でこの問題を説明します.以下のようにします.
ログに格納されているレコード数が500000件であると仮定すると、ソリューションは次のようになります.
ini_set(‘memory_limit’,’64M’);//phpをリセットする使用可能なメモリサイズは64 Mで、一般的にリモートホストでは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);//最初のユニットを削除-』
$farr = array_merge($farr,$arr);
unset($arr);
}
}
if(empty($this->farr)){
echo"関連記録なし! ";
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プログラムのメモリロスを節約するためには,静的変数の使用をできるだけ減らすべきであり,データ再利用が必要な場合には参照(&)の使用を考慮することができる.もう1つは、データベース操作が完了したら、すぐに接続を閉じることです.オブジェクトの使用が完了したら、構造関数(_destruct())をタイムリーに呼び出します.
二.unset変数を破棄し、メモリの問題を解放する
PHPのunset()関数は変数を消去、破棄するために使用され、使用しない変数はunset()で破棄することができます.しかし、unset()を使用すると、変数を破棄するために使用されるメモリに到達できない場合があります.まず例を見てみましょう
最後にunset()を出力する前にメモリを使用してunset()を減算した後にメモリを使用します.正数であれば、unset($s)がメモリから$sを破棄したことを示します(あるいは、unset()の後にメモリを使用して減少しました).しかし、PHP 5とwindowsプラットフォームの下では、0という結果になりました.これは、unset($s)が変数$sが消費するメモリを破棄する役割を果たしていないことを示していますか?次に例を示します.
この例は、上記の例とほぼ同じであり、唯一の違いは、$sが256個の1からなり、すなわち、第1の例より1個多くなり、結果は:272である.これは、unset($s)が$sで使用したメモリを破棄したことを示していますか?上記の2つの例から、unset()関数は、変数値が256バイトを超えるメモリ領域を占有する場合にのみメモリ領域を解放すると結論した.
では、変数値が256を超えるとunsetを使用してメモリ領域を解放できるのではないでしょうか.もう1つの例でテストしてみましょう.
ページをリフレッシュすると、最初の行は256個の1があり、2番目の行は0で、理屈では$sを破棄しましたが、$pは$sの変数を参照しているだけで、内容がないはずです.また、unset($s)前後のメモリ占有量は変わりません.次に、次の例を示します.
ページをリフレッシュすると、出力$pにはコンテンツがありません.unset()の前後のメモリ使用量の差は272です.つまり、変数が使用するメモリが消去されています.この例の$s=nullはunset()に変更することもできます.以下のようにします.
$sと$pの両方をunset()で破棄します.この場合、メモリの使用量の差も272であり、メモリを解放することもできます.では、メモリは、参照変数などの変数を指すすべての変数が破棄された場合にのみ解放されるという別の結論を得ることができます.
データ統計分析では、大きな配列に遭遇することが多く、メモリオーバーフローが発生する可能性があります.ここで私のソリューションを共有します.やはり例でこの問題を説明します.以下のようにします.
ログに格納されているレコード数が500000件であると仮定すると、ソリューションは次のようになります.
ini_set(‘memory_limit’,’64M’);//phpをリセットする使用可能なメモリサイズは64 Mで、一般的にリモートホストでは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);//最初のユニットを削除-』
$farr = array_merge($farr,$arr);
unset($arr);
}
}
if(empty($this->farr)){
echo"
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プログラムのメモリロスを節約するためには,静的変数の使用をできるだけ減らすべきであり,データ再利用が必要な場合には参照(&)の使用を考慮することができる.もう1つは、データベース操作が完了したら、すぐに接続を閉じることです.オブジェクトの使用が完了したら、構造関数(_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()の後にメモリを使用して減少しました).しかし、PHP 5と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の例より1個多くなり、結果は:272である.これは、unset($s)が$sで使用したメモリを破棄したことを示していますか?上記の2つの例から、unset()関数は、変数値が256バイトを超えるメモリ領域を占有する場合にのみメモリ領域を解放すると結論した.
では、変数値が256を超えるとunsetを使用してメモリ領域を解放できるのではないでしょうか.もう1つの例でテストしてみましょう.
<?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があり、2番目の行は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であり、メモリを解放することもできます.では、メモリは、参照変数などの変数を指すすべての変数が破棄された場合にのみ解放されるという別の結論を得ることができます.