Milan Kryl

Kryl Blog - RSS

PHP optimalizace 2

28. 05. 2004 - 00:02

Některé čtenáře příspěvek zaujal, takže se vracím s podrobnějším vysvětlením těch nejzajímavějších variant optimalizace stránek.

Dynamický obsah a cacheování

Nejjednodušší optimalizace dynamického webu je cacheování odpovědí na stejný dotaz. Když je požadována stránka se stejnými parametry, tak se vygeneruje její podoba do cache s časovou značkou. Odtud se bere cacheovaná statická verze stránky dokud nevyprší její platnost. Potom je odmazána a při dalším přístupu se znovu generuje do cache.

Jednoduchý příklad cacheování stránky za pomoci PEAR::Cache_Lite

    <?php
        /* Include the class */
        require_once('Cache/Lite.php');

        /* Set a key for this cache item */
        $id = 'newsitem1';

        /* Set a few options */
        $options = array(
            'cacheDir' => '/var/cache/news/',
            'lifeTime' => 3600
        );

        /* Create a Cache_Lite object */
        $Cache_Lite = new Cache_Lite($options);

        /* Test if there is a valid cache-entry for this key */
        if ($data = $Cache_Lite->get($id)) {
            /* Cache hit! */
        } else {
            /* Cache miss! */
            ob_start();
            /* Generate content */
            $data = ob_get_contents();
            $Cache_Lite->save($data);
        }
    ?>

Bohužel, pokud se na stránce něco změní, tak se změna projeví až po vypršení časového limitu cache. V příkladu po jedné minutě. Což pro některé aplikace nemusí být moc vhodné. Nelze např. po zveřejnění stránky a nelezení nějakých překlepů rychle chybu opravit. Zvlášť když je kvůli menší zátěži zvýšen interval, jak dlouho má zůstat stránka předgenerována.

Další nevýhodou je parsování stránky PHP procesorem. I když je provádění rychlejší, tak se stejně musí přechroustat.

Předgenerovaný obsah

Kód stránek je sice uložen v databázi, je přes nějaké administrační rozhraní editován. Na stránkách se ale zobrazuje ve statické podobě. Statický kód je generován pravidelně jednou za nějaký časový interval. Záleží na aktuálnosti dat, která jsou zobrazována na stránkách a také na velikosti webu. U jedné stránky, která je aktualizována velmi často může být generování prováděno jednou za minutu. V případě rozsáhlých firemních webů se naopak generování může provádět například jednou za hodinu. Případně lze spouštět generování jen na některé části a nebo jen jednotlivé stránky po aktualizaci jejich obsahu. (pokud spolu stránky nějak nesouvisí)

<?php 
    ob_start();                  // pozastavení výstupu
    include("table.php");        // veškerý výstup jde do bufferu 
    $buf = ob_get_contents();    // přiřazení výstupu do proměnné 
    ob_end_clean();              // vyčistit a vypnout buffer

    $fh = fopen("outfile.html","w");
    fwrite($fh, $buf);
    fclose($fh);
?> 

Oproti předchozímu příkladu má tu výhodu, že provedené změny se projeví po přegenerování stránky. Není třeba čekat na vypršení nějakých limitů a změny jsou viditelné ihned.

Dále se jedná již o čistě statický obsah bez jediného řádku php kódu, takže záleží už jen na webovém serveru jak rychle zvládne servírovat čistý html kód. PHP je použito jen jako mezivrstva pro generování stránek. A v tomto případě už myslím na limity nenarazíte. :-) To by museli být více než milióny požadavků a přinejhorším přidáte další server a budete požadavky distribuovat.

Bohužel tímto způsobem máme celý web dvakrát. Jednou je uložen v databázi a jednou je kompletně vygenerovaný na disku. I když při rostoucích kapacitách už to v dnešní době nemusí být takový problém.

Generování na požádání

Vychází z předpokladu, že většina stránek není na webu moc často zobrazována. Regenerování se provádí jen v případě zaslání požadavku za použití triku 404 stránky.

Celý fígl spočívá v tom, že si na webovém serveru nastavíte pro chybový kód 404 (stránka nenalezena) skript, který za vás odvede celou práci. Z url si vytáhne, která stránka vás zajímá, vygeneruje ji a zašle na výstup.

Příklad: máte zpravodajský server mynews.com, adresu http://mynews.com/news/0001.html, zprávy uložené v adresáři /home/httpd/news/

Nastavíte si do konfigurace apache ošetření stránky 404 vlastním skriptem (případně lze nastavení provést i přes .htaccess soubor pro jednotlivé adresáře, ale povolení těchto souborů zpomaluje webový server. (při každém požadavku musí kontrolovat, jestli v daném adresáři není .htaccess pro nějakou úpravu konfigurace)

<Directory /home/httpd/news>
    ErrorDocument 404 /generate-news.php
</Directory>

A skript generate-news.php

<?php
    $id = basename($_SERVER['REDIRECT_URL'], '.html');

    /* Generate the HTML */
    include("/home/httpd/news/generator.php");
    $html = generate_html($data);

    /* Show the page */
    echo $html;

    /* Store the page for later use */
    $fp = fopen(sprintf("/home/httpd/news/%04d.html", $id), "w");
    fputs($fp, $html);
    fclose($fp);
?>

Soubor se po vyřízení požadavku vygeneruje na správné místo a nějakou dobu tam zůstane. Každý den mohou být staré soubory (na které se dlouho nepřistupovalo, případně všechny) smazány. Taktéž lze statický soubor mazat po provedení některé úpravy. Při dalším požadavku je statická stránka vygenerována znovu a jede se dál.

Snad se mi podařilo podrobněji vysvětlit základní body letmo zmíněné v prvním dílu PHP optimalizací. Případně můžete také pokračovat ve čtení v dalším díle PHP optimalizací.

Prameny opět: Dick Rethans - Boosting The Performance of your PHP Applications a taky vlastní zkušenosti ;o)

 

Tip: Krátké zprávy a zajímavosti (rychlý přístup https://kryl.info/kratce)