Avatar billede birkbonnicksen Nybegynder
08. februar 2016 - 10:26 Der er 3 kommentarer og
1 løsning

Hvorfor æder mit php script memory?

Hej,

Jeg har et problem med at mit PHP script æder vildt meget memory på min apache server.

Jeg har installeret Xampp 5.6.15 med standardindstillinger.

Når jeg kører mit scripts i browseren (holder F5 nede for at siden refreshes en masse gange) kan jeg se i Windows Task Manager at memory forbruget for processen "Apache HTTP Server (32 bit)" stiger og stiger fra ca. 13,1MB til den begynder at sløve ned når den når omkring 140MB, men den stiger stadig.

En kunde der har kørt med scriptet en uges tid, hvor scriptet bliver kørt hvert 5 min ca., havde et forbrug på ovennævnte process i Task Manageren på ca. 450MB. Og det tog ca. 1 min i browseren at køre scriptet..

Det er ikke et særlig avanceret script så forstår ikke hvad der er galt..

Kan i hjælpe?

Scriptet finder og læser en tekst på en hjemmeside hvorefter den laver det om til et RSS-feed.

Scriptet ser sådan her ud:

<?php
    //echo memory_get_usage();
    //echo "\n";

    // ====
    // Parse html start
    // ====
    # Use the Curl extension to query Google and get back a page of results
    $url = "http://www.laesoe-line.dk/aktuelsejlads";
    $ch = curl_init();
    $timeout = 5;
    curl_setopt($ch, CURLOPT_URL, $url);
    $url = null;
    unset($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $timeout = null;
    unset($timeout);
    $html = curl_exec($ch);
    curl_close($ch);
    $ch = null;
    unset($ch);

    # Create a DOM parser object
    $dom = new DOMDocument();

    # Parse the HTML from Google.
    # The @ before the method call suppresses any warnings that
    # loadHTML might throw because of invalid HTML in the page.
    @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
    //@$dom->loadHTML($html);
    $html = null;
    unset($html);

    $scanHtml = false;
    $currentSailing = "Aktuel sejlads: ";

    # Iterate over all the <a> tags
    foreach($dom->getElementsByTagName('div') as $link) {
        # Show the <div id>
        if ($link->getAttribute('id') == "MainContent") {
            $scanHtml = true;
        }
        if ($scanHtml) {
            if ($link->getAttribute('class') == "Description") {
                $currentSailing = $currentSailing . $link->nodeValue . " ";
            }
        }
        if ($link->getAttribute('class') == "Clears") {
            $scanHtml = false;
            break;
        }
    }
    $link = null;
    unset($link);
    $dom = null;
    unset($dom);
    $scanHtml = null;
    unset($scanHtml);
    // ====
    // Parse html end
    // ====

    // ====
    // RSS feed start
    // ====
    header("Content-Type: application/rss+xml; charset=UTF-8");
   
    $rssfeed = '<?xml version="1.0" encoding="UTF-8"?>';
    $rssfeed .= '<rss version="2.0">';
    $rssfeed .= '<channel>';
    $rssfeed .= '<title>Fra Læsø Aktuel sejlads</title>';
    $rssfeed .= '<link></link>';
    $rssfeed .= '<description></description>';
    $rssfeed .= '<language>da-dk</language>';
    $rssfeed .= '<copyright></copyright>';

    /** Get current info **/
    $rssfeed .= '<item>';
    $rssfeed .= '<title>' . $currentSailing . '</title>';
    $currentSailing = null;
    unset($currentSailing);
    $rssfeed .= '</item>';

    $rssfeed .= '</channel>';
    $rssfeed .= '</rss>';

    echo $rssfeed;
    $rssfeed = null;
    unset($rssfeed);
    // ====
    // RSS feed end
    // ====

    //echo "\n";
    //echo memory_get_usage();
?>

Venlig hilsen Birk
Avatar billede olsensweb.dk Ekspert
08. februar 2016 - 10:44 #1
det lyder som du ikke får frigivet den hukommelse du har anvendt.

du kunne overveje at pakke din code ind i en function, da alt den hukommelse en function anvender, frigives efter afslutning af functionen.

du kunne også kigge på Garbage Collection
http://php.net/manual/en/features.gc.php
Avatar billede birkbonnicksen Nybegynder
08. februar 2016 - 11:16 #2
Det var en god ide at sætte al koden ind i en funktion, og så bare kalde funktionen i starten af scriptet. Tak.
Så slipper jeg for at huske at "unsette" alle variablerne, og lader Garbage Collectoren tage sig af det.

Hmm, men resultatet er det samme.. Hmm måske mit problem ikke er scriptet..
Avatar billede arne_v Ekspert
09. februar 2016 - 01:41 #3
Der er mange ting som jeg ikke forstaar.

$x = null;
unset($x);

boer ikke bruges.

140 MB er ingen ting paa computere som er koebt i dette aarhundrede.

Man koerer vel ikke produktion (kunder) paa XAMPP.

Du angiver ikke hvilken execution model du bruger: Apache mod eller fastcgi eller cgi - det er ret essentielt for en memory diskussion.

Der er rigtigt mange hits paa en google soegnig paa:

php curl memory leak

heriblandt en del som siger at:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true)

er broken (men eksempler synes dog at vaere for PHP 5.4 ikke 5.6).
Avatar billede birkbonnicksen Nybegynder
09. februar 2016 - 14:31 #4
Jeg har fjernet:

$x = null;
unset($x);

alle steder og sat koden ind i en funktion:

<?php
rss();
function rss() {
// kode fra script her
//
//
}
?>

Så lader jeg garbage collectoren tage sig af det..

Jeg har søgt på google efter "php curl memory leak", men det var til tidligere versioner af php. Det lød som om at memory leaket er rettet i version 5.3, og jeg bruger 5.6.15...

Men du har nok ret, 140MB er nok ikke meget for apache processen..
Og den bliver faktisk ikke ved med at stige, så jeg tog fejl..
Den stopper ved ca. 156,7MB og efter ca. 30 sekunder falder den til 148MB og senere falder den yderligere til ca. 135MB..

Så det ser ud til at det hele sikkert virker helt som det skal..

Undskyld forstyrrelsen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester