PHP bir bellek sızıntısı tespit gitmek nasıl

8 Cevap php

Benim PHP uygulama kayıtları alabilirsiniz bir ithalat komut dosyası vardır.

Şu anda, bir CSV dosyası ithal edilmektedir. Bu fgetcsv kullanarak bir anda CSV dosyası, bir satır her satırı okuyor, ve her bir hat için veritabanı sorguları bu kaydın üzerinde a lot işleme yapıyor, ve sonra bir sonraki satıra geçmeden . Bu daha fazla bellek biriken tutmak gerekmez.

Yaklaşık 2500 kayıtları ithal sonra, PHP bellek limitini (132 MB ya da öylesine) üzerinde çalıştırmak olduğunu söyleyerek, ölür.

Dize karşılaştırmaları, farklarını, vb Bunun üzerine faaliyet kodunun büyük miktarda var ve bir 'küçük çoğaltılması ile gelmek zor olacak bir çok şey yok olur, diğer işleme - CSV dosyası kendisi megs sadece bir çift örnek '.

Böyle bir sorunu bulma ve sabitleme gitmek için bazı iyi yolları nelerdir?

Cause of problem found

I have a debug class which logs all my database queries during runtime. So those strings of SQL, some 30KB long, were staying in memory. I realise this isn't suitable for scripts designed to run for a long time.

There may be other sources of memory leaks, but I am fairly sure this is the cause of my problem.

8 Cevap

Bu koda bir göz var yardımcı ama kendiniz hata ayıklamak istiyorsanız, Xdebug, bu uygulama profil yardımcı olacak bir göz olurdu.

Tabii ki, ne yapıyorsun bağlı olarak, 132MB 2500 kayıtları için zaten yüksek görünüyor olsa da, bazı bellek birikimi oluyor mümkündür. Tabii ki, tweak your memory limit php.ini gerekli eğer.

Okuduğunuz CSV dosyası ne kadar büyük? Ve bunun için işleme ne nesne ve tür yapıyorsun?

Aslında sadece bir ya da iki bellek sızıntıları çökmesine neden olan script içinde olduğunu şüphe yoksa, o zaman aşağıdaki adımları izleyin:

  • 500KB gibi Değişim memory_limit, küçük bir şey,
  • Her satır için uygulanan işlem adımlarından biri ama tüm dışarı comment.
  • Bütün CSV dosyası üzerinde sınırlı işleme çalıştırın ve onu tamamlamak görmek.
  • Yavaş yavaş daha fazla adım geri ekleyin ve eğer bellek kullanımı ani görmek için izleyin.

Örnek:

ini_set('memory_limit', 1024 * 500);
$fp = fopen("test.csv", 'r');
while($row = fgetcsv($fp)) {
    validate_row($row);         // step 1: validate
    // add these back in one by one and keep an eye on memory usage
    //calculate_fizz($row);     // step 2: fizz
    //calculate_buzz($row);     // step 3: buzz
    //triangulate($row);        // step 4: triangulate
}
echo "Memory used: ", memory_get_peak_usage(), "\n";

Kötü durum senaryosu all sizin işlem adımları orta verimsiz ve hepsini optimize etmek gerekir olmasıdır.

Bu, onlarla nasıl yapılıyor sonra değişkenleri temizleyen bağlıdır.

Eğer kaydı ile yapılır gibi görünüyor ama yine de bir yerde bilgi depolamak. unset() şüphe durumunda değişkenleri temizlemek için kullanın.

Bu yardım etmezse nerede tüm bu bellek gidiyor görmek için en az bir çoğaltma kod örneği verin.

Eğer dikkatle, tekrar kod geçmesi zorlar çünkü MEZUNLARI, sorunu yeniden edecek küçük kod örneği üreten büyük bir hata ayıklama tekniktir.

Eğer PHP5.3 yerel bir yükleme yapmayı deneyin ve http://www.php.net/manual/en/function.gc-collect-cycles.php diyebiliriz.

gc_collect_cycles - varolan herhangi bir çöp döngülerinin Kuvvetleri koleksiyonu

durum geliştirir eğer, en azından sorun (lar) (on) doğrulanmadı.

Nasıl dosyayı okuyorsun? Senin fread / filegetcontents veya benzeri fonksiyonları kullanarak sonra tüm dosya boyutunu tüketmek için gidiyoruz eğer tüm dosya arama anda yüklü olarak bellekte (ancak ya kadar freadla yük). Ancak sadece bu bellek üzerinde dramatikçe kolay olabilir hattının uzunluğuna bağlı olarak bir defada bir satır okuyacak eğer fgetcsv kullanırsanız.

Ayrıca her bir döngü üzerinde mümkün olduğu kadar çok değişken yeniden emin olun. Onlara büyük miktarda veri ile herhangi bir dizi var olup olmadığını kontrol edin.

Son bir not olarak da o afterwords kapatmadan Eğer döngü önce dosyayı açmadan emin olun:

$fh = fopen(...);
while(true)
{
//...
}
fclose($fh);

Siz gerçekten bu yapıyor olmak istemiyorum:

while(true)
{
$fh = fopen(...);
//...
fclose($fh);
}

Ve diğerleri gibi bazı kod görmeden söylemek zor olacak dedi.

Bu herhangi bir kod görmeden nedenini söylemek zor. Ancak, tipik bir konudur, yani özyinelemeli referanslar olduğunu. B ve GC berbat neden olabilir etrafında başka bir yol, itiraz için bir puan nesne.

Ben şu anda dosyası işleme konum nasıl bilmiyorum, ama sadece bir seferde dosya bir satır okumak için çalışabilir. Bir kerede tüm dosyayı okursanız daha fazla bellek tüketebilir.

Bu aslında sık sık toplu işleme görevleri için Python tercih nedenlerinden biridir.

Eğer php.ini içinde memory_limit değiştirmek yapabiliyor musunuz?

Ayrıca, bazı bellek boşaltmak değişkenlerin unset ($ var) yapıyor olabilir? Çok var = null yardım $ misiniz?

Ayrıca bu soruya bakın: http://stackoverflow.com/questions/584960/whats-better-at-freeing-memory-with-php-unset-or-var-null

Ben aynı sorunu yaşıyorum, ve bu nedeniyle veritabanı profilleme (Zend_Db_Profiler_Firebug) de oldu. Benim durumumda bu dakikada 1mb sızıntı oldu. Bu komut gün boyunca çalıştırmak gerekiyordu, bu yüzden bir kaç saat içinde çökebilir.