回答:
それは2009年にunsetマニュアルのページで言及されました:
unset()
その名前のとおりに実行します-変数の設定を解除します。メモリの即時解放は強制されません。PHPのガベージコレクターは、適切だと判断したときにそれを実行します。意図的に、これらのCPUサイクルが不要になったとき、または最初に発生するスクリプトがメモリ不足になる前に遅くなります。実行している
$whatever = null;
場合は、変数のデータを書き換えています。あなたはより速くメモリを解放/縮小するかもしれませんが、それは本当にそれらをより早く必要とするコードからCPUサイクルを奪い、結果として全体的な実行時間をより長くするかもしれません。
(2013年以降、そのunset
manページにはそのセクションが含まれなくなりました)
php5.3までは、2つのオブジェクトが循環参照(親子関係など)している場合、親オブジェクトでunset()を呼び出しても、子オブジェクトの親参照に使用されていたメモリは解放されません。(または、親オブジェクトがガベージコレクションされたときにメモリが解放されることもありません。)(バグ33595)
「unsetと= nullの違い」という質問は、いくつかの違いを詳しく説明しています。
unset($a)
$a
シンボルテーブルからも削除します。例えば:
$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);
出力:
Notice: Undefined variable: a in xxx
NULL
しかし、いつ
$a = null
使用されるか:
$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);
Outputs:
NULL
それはそれ
$a = null
よりも少し速いようですunset()
:シンボルテーブルエントリの更新はそれを削除するより速いようです。
unset
)変数と、エラーがトリガーされ、変数式の値はnullになります。(なぜなら、PHPは他に何をすべきか?すべての式が何らかの値をもたらす必要があるからです。)unset
実際には関数ではありませんが、言語構造です。これは、a return
またはにすぎませんinclude
。
パフォーマンスの問題は別として、を使用unset
すると、コードの意図がより明確になります。
unset
としてUnSeT
、たとえば、。コミュニティーは、スタイルの問題としてすべて小文字で解決していますが、他の大文字小文字は引き続き機能します。
変数に対してunset()を実行すると、基本的に変数に「ガベージコレクション」のマークが付けられます(PHPには実際には1つはありませんが、たとえば)。これにより、メモリがすぐに使用できなくなります。変数にはデータが格納されなくなりましたが、スタックはより大きなサイズのままです。nullメソッドを実行すると、データが削除され、スタックメモリがすぐに縮小されます。
これは、個人的な経験や他の人たちからのものです。ここで unset()関数のコメントを参照してください。
個人的には、ループの反復間でunset()を使用して、スタックのサイズがヨーヨーになるのを遅らせる必要がないようにしています。データはなくなりましたが、フットプリントは残っています。次の反復では、メモリはすでにphpによって使用されているため、次の変数をより早く初期化できます。
<?php
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
$a = NULL;
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
unset($a);
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
?>
「= null」の方が速いようです。
PHP 5.4の結果:
PHP 5.3の結果:
PHP 5.2の結果:
PHP 5.1の結果:
PHP 5.0と4.4では物事が異なって見え始めます。
5.0:
4.4:
PHP 4.4ではmicrotime(true)は機能しないので、php.net / microtime /例1にあるmicrotime_floatの例を使用する必要があることに注意してください。
unset
はより高速です。私は後でunset
ケースの存在をチェックするテストがあります。そのテストでnull
は、それを設定するとわずかに速くなります。テスト:pastebin.com/fUe57C51
gc_collect_cycles
より正確な結果を得るために、常にタイマーを開始する前に呼び出します。
それは配列要素と違いを生みます。
この例を考えてみましょう
$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
ここでは、キー「テスト」がまだ存在しています。ただし、この例では
$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
キーは存在しません。
参照によってコピーされた変数に対しては、別の方法で機能します。
$a = 5;
$b = &$a;
unset($b); // just say $b should not point to any variable
print $a; // 5
$a = 5;
$b = &$a;
$b = null; // rewrites value of $b (and $a)
print $a; // nothing, because $a = null
オブジェクトに関して、特にレイジーロードのシナリオでは、ガベージコレクターがアイドルCPUサイクルで実行されていることを考慮する必要があります。そのため、多くのオブジェクトが短い時間でロードされているときに問題が発生すると想定すると、メモリの解放が解決されます。
GCがメモリを収集できるようにするには、time_nanosleepを使用します。変数をnullに設定することをお勧めします。
本番サーバーでテストしましたが、最初はジョブが50MBを消費し、その後停止しました。nanosleepが使用された後、14MBは一定のメモリ消費でした。
これは、PHPのバージョンによって異なるGCの動作に依存すると言うべきです。しかし、PHP 5.3では問題なく動作します。
例えば。このサンプル(VirtueMart2 googleフィードから取得したコード)
for($n=0; $n<count($ids); $n++)
{
//unset($product); //usefull for arrays
$product = null
if( $n % 50 == 0 )
{
// let GC do the memory job
//echo "<mem>" . memory_get_usage() . "</mem>";//$ids[$n];
time_nanosleep(0, 10000000);
}
$product = $productModel->getProductSingle((int)$ids[$n],true, true, true);
...
まだ疑っていますが、スクリプトで試しましたが、xdebugを使用して、アプリのメモリ使用量にどのように影響するかを確認しています。スクリプトは次のように私の関数に設定されています:
function gen_table_data($serv, $coorp, $type, $showSql = FALSE, $table = 'ireg_idnts') {
$sql = "SELECT COUNT(`operator`) `operator` FROM $table WHERE $serv = '$coorp'";
if($showSql === FALSE) {
$sql = mysql_query($sql) or die(mysql_error());
$data = mysql_fetch_array($sql);
return $data[0];
} else echo $sql;
}
そして、return
コードの直前にunsetを追加すると、160200が得られます。次に、それを変更しようとすると、$sql = NULL
160224が得られます:)
しかし、私がunset()またはNULLを使用していない場合、この比較にはユニークなものがあります。xdebugはメモリ使用量として160144を与えます
したがって、unset()またはNULLを使用する行を指定すると、アプリケーションにプロセスが追加され、コードの原点を維持し、使用している変数をできるだけ効果的に減らす方が良いと思います。
私が間違っていたら訂正してください、ありがとう
私はのための新しいパフォーマンス・テストを作成unset
し、=null
コメントで述べたように、ここで記述されたが、エラー(要素の再作成を)持っているので、。今は問題ではないように、私は配列を使用しました。
<?php
$arr1 = array();
$arr2 = array();
for ($i = 0; $i < 10000000; $i++) {
$arr1[$i] = 'a';
$arr2[$i] = 'a';
}
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$arr1[$i] = null;
}
$elapsed = microtime(true) - $start;
echo 'took '. $elapsed .'seconds<br>';
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
unset($arr2[$i]);
}
$elapsed = microtime(true) - $start;
echo 'took '. $elapsed .'seconds<br>';
しかし、私はPHP 5.5.9サーバーでのみテストできます、ここでは結果:-4.4571571350098秒かかりました-4.4425978660583秒かかりました
私unset
は読みやすさの理由で好みます。
PHP 7は、このようなメモリ管理の問題と、その使用量を最小限に抑えられるようにすでに取り組んでいます。
<?php
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
$a = NULL;
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
unset($a);
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
?>
PHP 7.1出力:
0.16778993606567秒かかりました0.16630101203918秒かかりました
unset
即時メモリを解放しない場合でもコードは非常に役立ち、メソッドを終了する前にコードステップを渡すたびにこれを行うことをお勧めします。即時メモリの解放についてではないことに注意してください。即時メモリはCPU用で、RAMであるセカンダリメモリはどうでしょうか。
また、これはメモリリークの防止にも取り組みます。
このリンクを参照してください http://www.hackingwithphp.com/18/1/11/be-wary-of-garbage-collection-part-2
私は長い間unsetを使用しています。
すでに配列として使用されているすべての変数の設定を常に解除するために、コードでこのようなより良い実践をしてください。
$data['tesst']='';
$data['test2']='asdadsa';
....
nth.
そしてjust unset($data);
、すべての変数の使用を解放します。
設定を解除するには、関連トピックを参照してください
[バグ]
記録のために、そしてそれがかかる時間を除いて:
<?php
echo "<hr>First:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Unset:<br>";
unset($x);
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Null:<br>";
$x=null;
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>function:<br>";
function test() {
$x = str_repeat('x', 80000);
}
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Reasign:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
戻る
First:
438296
438352
Unset:
438296
438352
Null:
438296
438352
function:
438296
438352
Reasign:
438296
520216 <-- double usage.
結論、期待どおりのnullと未設定の両方の空きメモリ(実行の終了時だけでなく)。また、変数を再割り当てすると、ある時点で値が2回保持されます(520216対438352)
$whatever
オブジェクトを指す場合$whatever = null
、オブジェクト自体ではなくポインタを上書きするため、基本的にはと同じように動作しunset()
ます。