2010-08-15 16 views
5

Bir zamanlayıcılığa karşı koyduğumda, giderek yavaşlayan bir komut dosyası var. Her şey yaptığı gibi bir satır okur, kontrol eder, daha sonra veritabanına ekler ve bir sonraki satıra kadar ilerler gibi oldukça basittir.PHP betiği aşamalı olarak yavaşlıyor (dosya okuyucu)

Record: #1,001 Memory: 1,355,360kb taking 1.84s 
Record: #1,001 Memory: 1,355,360kb taking 1.84s 
Record: #2,002 Memory: 1,355,192kb taking 2.12s 
Record: #3,003 Memory: 1,355,192kb taking 2.39s 
Record: #4,004 Memory: 1,355,192kb taking 2.65s 
Record: #5,005 Memory: 1,355,200kb taking 2.94s 
Record: #6,006 Memory: 1,355,376kb taking 3.28s 
Record: #7,007 Memory: 1,355,176kb taking 3.56s 
Record: #8,008 Memory: 1,355,408kb taking 3.81s 
Record: #9,009 Memory: 1,355,464kb taking 4.07s 
Record: #10,010 Memory: 1,355,392kb taking 4.32s 
Record: #11,011 Memory: 1,355,352kb taking 4.63s 
Record: #12,012 Memory: 1,355,376kb taking 4.90s 
Record: #13,013 Memory: 1,355,200kb taking 5.14s 
Record: #14,014 Memory: 1,355,184kb taking 5.43s 
Record: #15,015 Memory: 1,355,344kb taking 5.72s 

dosya maalesef her şey artış hızında okunur zaman etrafında ~ 20 gb yüzden muhtemelen ölmüş olacağım geçerli:

Burada yavaş yavaş kötüye gidiyor bunun çıkışı var. Kod aşağıda (esas olarak), ancak fgets() ile ilgili bir şey olduğundan şüpheleniyorum, ama ne olduğundan emin değilim.

$handle = fopen ($import_file, 'r'); 

    while ($line = fgets ($handle)) 
    { 
     $data = json_decode ($line); 

     save_record ($data, $line); 
    } 

Şimdiden teşekkürler!

DÜZENLEME:

üzerinden yorumda 'save_record ($ veri $ hattı); hiçbir şey yapmıyor gibi görünüyor.

+0

Kaydetme için kod kaydedebilir misiniz? Muhtemelen anahtar olan – Jhong

+0

Aslında save_record() satırına yorum yaparsam, yine de kötü. – DCD

+1

Bu performans çıktısını nasıl alıyorsunuz? Sağladığınız kod örneğinde performans kayıt olmuyor. Problemin başka yerlerde olduğundan şüpheleniyorum. Bizi ilgilendirmeyeceğiniz bazı kodlarınız var mı? –

cevap

0

Alright, bir performans sorunu belirtmek

çok daha hızlı. Belli ki bir şey yapmaması gerektiğinde kuadratikleşiyor, ya da daha fazla noktaya, sabit zaman olması gereken bir şey, şimdiye kadar ele alınan kayıtların sayısında doğrusal gibi görünüyor. İlk soru, problemi sergileyen asgari kod hurdasıdır. Ben de aynı problemli davranışı elde edip edemeyeceğinizi bilmek istiyorum. Eğer öyleyse, o zaman sorun olmadan bir dile ihtiyacınız olacaktır. (Çok fazla var.) Her neyse, beklenen zaman karakteristiğini gördüğünüzde, zamanlamanız işlenene kadar ifadeleri birer birer ekleyin ve sorunu tanımlayın.

Zamanlamaları almak için bir şey ya da başka bir enstrüman verdiniz. Bunların, yalnızca yaklaşık 15000 kez çalıştırılarak bir soruna yol açmayacağından emin olun.

1

Bazen bu büyük dosyaları okumak için sistem komutlarını kullanmak daha iyidir. Ben benzer bir şey ile karşılaştım ve burada kullanılan küçük bir hile:

$lines = exec("wc -l $filename"); 
for($i=1; $i <= $lines; $i++) { 
    $line = exec('sed \''.$i.'!d\' '.$filename); 

    // do what you want with the record here 
} 

ben güvenilemez dosyalarla bu tavsiye etmem, ama bu sistemi kullanarak her seferinde bir rekor çeker çünkü hızlı çalışır. Bu yardımcı olur umarım.

+0

+1 iyi bir fikir, bunu gelecekte ele alacağım. – alex

0

Daha hızlı bir şekilde bir 96G metin dosyasına giderken bir yol bulmaya çalışırken bu soruyu buldum. İlk yazdığım senaryo 15 saatte% 0.1 ...

Burada önerilen çözümlerden bazılarını stream_get_line, fgets ve sed için çalıştırmayı denedim. Bu soruya engel olan başkalarıyla paylaşacağımı düşündüğüm farklı bir yaklaşımla sonuçlandım.

Dosyayı böl! :-)

Benim freebsd kutumda (linux ve diğerleri için de var) Ben 'split' adlı bir komut satırı yardımcı programı var.

 
usage: split [-l line_count] [-a suffix_length] [file [prefix]] 
     split -b byte_count[K|k|M|m|G|g] [-a suffix_length] [file [prefix]] 
     split -n chunk_count [-a suffix_length] [file [prefix]] 
     split -p pattern [-a suffix_length] [file [prefix]] 

Ben de kaçtım:

 
split -l 25000 -a 3 /data/var/myfile.log /data/var/myfile-log/ 

Sonra sonra tüm bir komutla teker teker işlenebilir olabilir/veri/var/dosyam-log/dizinindeki 5608 dosyaları ile sona erdi gibi:

 
php -f do-some-work.php /data/var/myfile-log/*