2012-01-12 14 views
5

Uruchomiłem poniższy kod PHP z wiersza poleceń. Problem polega na tym, że zużycie pamięci znacznie przekracza to, co powinno być. Nie potrafię, na całe życie, dowiedzieć się, gdzie pamięć się zużywa.Problem z wyciekiem pamięci skryptowej PHP

for ($i=0;$i<100;$i++) 
     { 
      $classObject = $classObjects[$i];      

      echo $i . " : " . memory_get_usage(true) . "\n"; 
      $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap);   
      unset($classDOM);   
     } 

Według mnie, pamięć zużywana przez mój skrypt powinna pozostać mniej więcej stała po każdej iteracji pętli. Każda pamięć konsumowana przez $scraper->scrapeClassInfo() powinna zostać zwolniona, gdy jej członkowie wykroczą poza zakres.

To jest plik wyjściowy, który otrzymuję. Dla zwięzłości, mam pokazując co 10 linii wyjścia:

0 : 5767168 
10 : 12058624 
20 : 18350080 
30 : 24903680 
40 : 30932992 
50 : 37748736 
60 : 43778048 
70 : 49807360 
80 : 55836672 
90 : 62914560 
97 : 66846720 

Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 44 bytes) in /home/content/60/8349160/html/drexel/simple_html_dom.php on line 1255 

Wreszcie, o ile widzę, co $scraper->scrapeClassInfo() robi naprawdę nie powinno być zainstalowane, ale tylko w przypadku, tutaj kod:

function scrapeClassInfo($class,$termMap,$subjectMap) 
     { 
      $ckfile = tempnam ("/tmp", "CURLCOOKIE"); 
      $ckfile2 = tempnam ("/tmp", "CURLCOOKIE2"); 
      $ckfile3 = tempnam ("/tmp", "CURLCOOKIE3");   

      $termpage = $termMap[$class['termcode']]; 
      $subjectpage = $subjectMap[$class['subjectcode']]; 
      $classpage = $class['classlink']; 

      //hit the main page and get cookie 
      $ch = curl_init(); 
      curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); 
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
      curl_setopt($ch, CURLOPT_URL, $this->mainURL); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
      curl_exec($ch); 
      curl_close($ch); 

      //hit the term page and get cookie 
      $ch = curl_init(); 
      curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); 
      curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile2); 
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
      curl_setopt($ch, CURLOPT_URL, $termpage); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
      curl_exec($ch); 
      curl_close($ch); 

      //hit the subject page and get cookie 
      $ch = curl_init(); 
      curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile3); 
      curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile2); 
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
      curl_setopt($ch, CURLOPT_URL, $subjectpage); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
      curl_exec($ch); 
      curl_close($ch); 

      //hit the class page and scrape 
      $ch = curl_init();    
      curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile3); 
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
      curl_setopt($ch, CURLOPT_URL, $classpage); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
      $result = curl_exec($ch); 
      curl_close($ch); 

      return str_get_html($result); 
     } 

metoda nazywa się w ostatnim wierszu, str_get_html() jest członkiem Simple HTML DOM Parser

Gdyby to znaczenia, to w jaki sposób wzywam mój skrypt:

/usr/local/php5/bin/php index.php 2>&1 1>output

Odpowiedz

3

W porządku, wymyśliłem to. Najwyraźniej jest to błąd, na którym cierpi cała wersja PHP przed 5.3. Ustawienie CURLOPT_RETURNTRANSFER do CURLOPT_RETURNTRANSFER na powoduje ogromne przecieki pamięci.

Pobiegłem skrypt ponownie, tym razem powołując się na PHP 5.3 binarny:

/web/cgi-bin/php5_3 index.php 2>&1 1>output 

i plik wyjściowy brzmi:

0 : 6291456 
10 : 9437184 
20 : 10747904 
30 : 11534336 
40 : 11534336 
50 : 11534336 
60 : 11534336 
70 : 11534336 
80 : 11534336 
90 : 11534336 
99 : 11534336 
152.74998211861 sec 

Teraz to, co mówię! Idealnie stały ślad pamięci.

+0

Co to jest błąd? –

+0

Kiedy napisałem "Ustawienie CURLOPT_RETURNTRANSFER na true" chciałem napisać "Ustawienie CURLOPT_RETURNTRANSFER na prawdziwe powoduje ogromne wycieki pamięci". Edytowane. – xbonez

+0

Aha. +1 za wyjaśnienie. –

1

Znalazłem następujące w twoim kodzie.

  1. Usuń curl_setopt($ch, CURLOPT_RETURNTRANSFER, true), ponieważ nie przechwytujesz go.
  2. Nie zamykaj rękojeści. Użyj go ponownie.

W bieżącym obejście można uruchomić skrypt php z wyższym memroy_limit

$ php -d memory_limit=1G /path/to/script 

1G oznacza 1 gigabajt.

+0

Dzięki. Zdecydowanie we właściwym kierunku. Próbowałem usunąć 'CUROPT_RETURNTRANSFER', ale w ostatnim żądaniu curl, które stworzyłem, musiałem go opuścić, więc nadal miałem problem z pamięcią. Tak czy inaczej, zobacz moją odpowiedź poniżej. – xbonez

Powiązane problemy