Diziler unsetting sonra PHP bellek kullanımı artış?

4 Cevap

Ben diziler unsetting olmadan ve daha sonra PHP'nin kullanarak diziler unsetting ile aşağıdaki kodu çalıştırmak

unset (array-$ burada)

Ben unset kullandığınızda ve bellek sayı artar. Herhangi bir fikir neden? Ve daha iyisi, belleği boşaltmak için doğru yolu nedir?

NOTICE: PLEASE, no preaching about pre-optimizing, its EVIL and all that, this is a test so don't lecture about it please and thank you.

//show current memory usage BEFORE
echo memory_get_usage() . "\n"; // 57960

//start timer
$start3 = microtime(true);
// arrays for header menu selector
$header_home = array('home'  => true);
$header_users = array('users.online' => true, 'users.location' => true, 'users.featured' => true, 'users.new' => true, 'users.browse' => true, 'users.search' => true, 'users.staff' => true);
$header_forum = array('forum' => true);
$header_more = array('widgets'  => true, 'news'  => true, 'promote'  => true, 'development'  => true, 'bookmarks'  => true, 'about'  => true);
$header_money = array('account.money' => true, 'account.store' => true, 'account.lottery' => true, 'users.top.money' => true);
$header_account = array('account'  => true);
$header_mail = array('mail.inbox' => true, 'mail.sentbox' => true, 'mail.trash' => true, 'bulletins.post' => true, 'bulletins.my' => true, 'bulletins' => true);

//run throught 1,000 iterations
for($i = 0; $i < $iterations; ++$i) {
if(isset($header_home[$p]))
    $current_home = 'current';
else if(isset($header_users[$p]))
    $current_users = 'current';
else if(isset($header_forum[$p]))
    $current_forum = 'current';
else if(isset($header_more[$p]))
    $current_more = 'current';
else if(isset($header_money[$p]))
    $current_money = 'current';
else if(isset($header_account[$p]))
    $current_account = 'current';
else if(isset($header_mail[$p]))
    $current_mail = 'current';
}
//unset the arrays
unset($header_money);
unset($current_home);
unset($current_users);
unset($current_forum);
unset($current_more);
unset($current_account);
unset($current_mail);

//show time
$end3 = microtime(true);
echo number_format($end3 - $start3, 7) . ' Time3 ARRAY<br />';

//show current memory usage AFTER
echo memory_get_usage() . "\n";

4 Cevap

Ben bu işlemi yaptıktan sonra, çok hızlı bir test yaptım:

  • $iterations = 10; yazısının başında ilan
  • kullanarak $p olup $i olarak döngü için (Eğer $p dizi elemanları erişmek için kullandığınız, ve $i)
  • boşaltır önce kullanılan bellek görüntülemek için bir satır ekleyerek

PHP 5.3.1 kullanarak, bu almak (today's snapshot) am:

328616
332176
331728

Üç çıkışları şunlardır:

  • Birincisi: senaryonun başlangıcı (diyene "show current memory usage BEFORE")
  • İkincisi: Ben unset aramalardan önce eklenen bir; sadece for döngünün sonunda
  • Üçüncüsü: Eğer komut sonunda koymak biri.

Yani, boşaltır aslında bazı bellek kurtuluş kışkırtmak, ve bellek artışı kullanılmaz ;-)

Ama ayrılan bellek yalnızca oldukça küçük bir kısmı serbest ...


Now, the question might be "what is causing some memory to be used and not freed, event if I call unset on the arrays" -- actually, it is probably what you first meant ?

Eh, ben kendilerini diziler içindeki öğeler için ayrılan belleği boşaltmak için PHP zorlamaz diziler unsetting herhalde ...

this note on the unset manual page says (alıntı) gibi:

unset() does just what it's name says - unset a variable. It does not force immediate memory freeing. PHP's garbage collector will do it when it see fits - by intention as soon, as those CPU cycles aren't needed anyway, or as late as before the script would run out of memory, whatever occurs first.

If you are doing $whatever = null; then you are rewriting variable's data. You might get memory freed / shrunk faster, but it may steal CPU cycles from the code that truly needs them sooner, resulting in a longer overall execution time.

Ve aslında, bu ilginç görünebilir ;-)

Yine de, hızlı testler birkaç yapıyor oldukça ilginç bir şey almaz; Benim komut / veri kullanılmayan belleği, veya böyle bir şey ücretsiz PHP zorlamak için yeterince büyük değil herhalde ...


Note : if I use gc_collect_cycles (PHP >= 5.3) to force a garbage collection after the unsets, it doesn't change a thing -- I suppose it's because there is no "lost cycle".


*BTW : running your code gave me quite a couple notices (the $p vs $i, for instance) ; do you develop with error_reporting set to report notices ? *

Sen diziler var olmadan önce memory_get_usage() olduğu için ilk çağrı konum. Sen kreasyonlar diziler + dolgu ve unset() 'ler bunu yapmalıyım

Burada gördüğünüz fazla bellek başında daha yazısının sonunda kullanılır sadece olmasıdır.

unset() is not "kuvvet çöp toplama" mekanizması.

Yani unset() değişkeni tuttuğunu bellek anlamına gelmez çağırıyor sadece değişken çöp toplama için planlanan demektir, anında kullanılabilir. PHP motoru, kendi zamanında yapar.

Bu herhangi bir fark olmadığını bilmiyorum, ama unset $start3, $end3 ve {dışında diğer her $home_xxx dizisi vermedi [(3)] }.

Ayrıca ben daha basit kriter tutmak öneririz. Gibi sadece örneğin bir dizi kullanarak.

Basit tutun. Bu test / benchmark daha anlamlı kılacaktır.

EDIT:

Sadece onunla biraz etrafında oynadı ..

First Test

<?php
$array = array();

echo "START:". memory_get_usage() . "\n";


for ( $i = 0; $i<1000; $i++ ) {
    $array[] = 'foo';
}

echo "BEFORE UNSET: " . memory_get_usage() . "\n";

unset($array);
echo "AFTER UNSET: " . memory_get_usage() . "\n";

sleep(120);
echo "AFTER A WHILE: " . memory_get_usage() . "\n";

Çıktı:

START:53632
BEFORE UNSET: 146360
AFTER UNSET: 118848
AFTER A WHILE: 118848

Second test:

<?php
$array = array();

echo "START:". memory_get_usage() . "\n";


for ( $i = 0; $i<1000; $i++ ) {
    $array[] = 'foo';
}

echo "BEFORE UNSET: " . memory_get_usage() . "\n";

for ( $i = 0; $i<count($array); $i++ ) {
    unset($array[$i]);
}
unset($array);
echo "AFTER UNSET: " . memory_get_usage() . "\n";

Çıktı:

START:53944
BEFORE UNSET: 146680
AFTER UNSET: 119128

Yani çöp toplama için unset sadece programları tutmaz ki teori (en azından PHP 5.2.8, ama sonra yine onlar PHP 5.3 GC çok değişti).

Ben unset :-( daha yapabileceğiniz çok daha fazla yok korkuyorum