Büyük xml beslemeleri ithal Sorunları (LAMP)

4 Cevap php

Herkes i deneyim ben biraz cron konuda bana yardımcı olabilir merak ediyorum

Sorun yükü 5'e kadar başak olabilir, ve CPU kullanımı çift çekirdekli 356Mb RAM ile 'Xeon L5410@2.33GHz' üzerinde,% 40 atlayabilir, ve ben kodu verdiği nereye emin değilim ve hangi yolu bunu önlemek için. Aşağıdaki kod örneği

//Note $productFile can be 40Mb .gz compressed, 700Mb uncompressed (xml text file) if (file_exists($productFile)) {

  $fResponse = gzopen($productFile, "r");
  if ($fResponse) {

     while (!gzeof($fResponse)) {

        $sResponse = "";
        $chunkSize = 10000;
        while (!gzeof($fResponse) && (strlen($sResponse) < $chunkSize)) {
          $sResponse .= gzgets($fResponse, 4096);
        }
        $new_page .= $sResponse;
        $sResponse = "";
        $thisOffset = 0;
        unset($matches);

        if (strlen($new_page) > 0) {

           //Emptying
           if (!(strstr($new_page, "<product "))) {
              $new_page = "";
           }

           while (preg_match("/<product [^>]*>.*<\/product>/Uis", $new_page, $matches, PREG_OFFSET_CAPTURE, $thisOffset)) {

              $thisOffset = $matches[0][1];
              $thisLength = strlen($matches[0][0]);
              $thisOffset = $thisOffset + $thisLength;

              $new_page   = substr($new_page, $thisOffset-1);
              $thisOffset = 0;

              $new_page_match = $matches[0][0];

              //- Save collected data here -//

              }

           }//End while loop


        }

     }
     gzclose($fResponse);
  }

}

$ ChunkSize - aşağı bellek kullanımını tutmak ve düzenli ifadeyi kolaylaştırmak için mümkün olduğunca küçük olmalı, ya da çalıştırmak için çok uzun sürüyor kod önlemek için büyük olmalıdır.

40.000 maçlarda yük / CPU kramponları ile. Yani herkes Crons aracılığıyla geniş besleme yüklemelerini yönetmek konusunda herhangi bir tavsiye var.

Yardımlarınız için şimdiden teşekkürler

4 Cevap

En azından iki sorun var. İlk belleğe tamamını 700 MB dosyayı açmak için çalışıyoruz olduğunu. Aslında, iki kez yapıyoruz.

while (!gzeof($fResponse) && (strlen($sResponse) < $chunkSize)) {
    $sResponse .= gzgets($fResponse, 4096);
}
$new_page .= $sResponse;

Her iki $sResponse ve $new_page eventaully tamamını 700 MB bir dosya içeren bir dize yapacak. Böylece PHP, diğer dillere göre daha iyi dizeleri işleme sırasında (string birleştirme maliyeti söz değil, komut çalıştıran bitirir zaman kadar yiyorsanız bellek 1.4 GB bulunuyor, değişken vs olmayan değişken alacak ne bir sınırı vardır siz)

İkinci sorun $new_page olarak giderek daha büyük dize üzerinde bir düzenli ifade koşuyoruz olduğunu. $new_page daha büyük ve büyüdükçe bu sunucu üzerinde artan yük koyacağız.

Sorunları çözmek için en kolay yolu, görevleri bölmek olduğunu.

  1. Herhangi bir işlem yapmadan önce diske tüm dosya sıkıştırması.

  2. Gibi bir steram tabanlı XML çözümleyici, kullanın XMLReader or the old SAX Event Based parser.

  3. Hatta bir akım / olay tabanlı ayrıştırıcı, sonuçları hafızasında saklayarak ram bir sürü yemek sona erebilir. Bu durumda, her maçı almak ve in-a-veritabanı disk / üzerinde saklamak isteyeceksiniz.

http://stackoverflow.com/questions/752337/suggestions-tricks-for-throttling-a-php-script/752441#752441: Eğer lamba kullanarak söylediler beri, benim sorulardan birine cevap önerebilir

O sunucuyu bogging şansını düşürmek için soruna senaryo üzerinde nice komutunu kullanarak önerir.

Alternatif senaryoyu profili ve herhangi bir darboğaz nerede görmek olacaktır. Ben XDebug ve KCacheGrind veya webcachegrind öneriyoruz. Eğer kurulum komut profilleme yardımcı sayısız soru ve mevcut web siteleri vardır.

You may also want to look at PHP's SAX event-based XML parser - http://uk3.php.net/manual/en/book.xml.php

Bu büyük XML dosyalarını ayrıştırma için iyidir (biz sizinle ilgilenen bir benzer büyüklükteki XML dosyaları için kullanabilirsiniz) ve bu oldukça iyi bir iş yok. Regexes için gerek yok o zaman :)

Bunu işleme ilk önce dosya sıkıştırmasını gerekiyordu.

Alan yeniden. O $ ChunkSize ulaşır ve $ new_page eklenmiştir sonra $sResponse anında temizlenir gibi görünüyor gibi komut dosyası, bellekte 700MB tutun asla

$new_page .= $sResponse;
$sResponse = "";

ve $new_page kez azaltılmış her maç bulundu ve olası bir eşleşme varsa her veri $ ChunkSize yığın için, temizlenir strlen edilir.

$new_page   = substr($new_page, $thisOffset-1);

if (!(strstr($new_page, "<product "))) {
   $new_page = "";
}

Ben asıl sorun burada yatıyor ben görebiliyorum diyemeyiz rağmen.