Afgelopen dinsdag heeft Byte een kleine wijziging doorgevoerd aan de huidige PHP5 installatie op alle web- en applicatieservers. Deze wijziging is uitgebreid getest in onze testomgeving, en is ontwikkeld om een flinke performancewinst te boeken. Uit testen bleek dat het, afhankelijk van het gebruikspatroon van een website/webapplicatie een performancewinst van enkele tientallen procenten kon leveren. De uiteindelijke resultaten liegen er niet om …

Om de performance van onze clusters in de gaten te houden hebben we op alle clusters monitoring staan, die periodiek een aantal voor websites belangrijke snelheidskenmerken meten: databasequeries, webserverprocessor en, een van de meest bepalende, het inlezen van een groot aantal bestanden. Op dat laatste kenmerk is deze aanpassing in PHP gericht. Om de resultaten maar direct te verklappen: onze performancetest laat een snelheidswinst van 40% zien.

Fileperformance cluster 1 (lager is beter)
Fileperformance cluster 1 (lager is beter)

Deze test, c1_files_deep, opent een groot aantal bestanden in een grote directorystructuur, net als een PHP-applicatie dat ook zou doen middels include(). Onze storage is bijzonder snel en efficient, maar uiteindelijk staan de bestanden nog steeds op mechanische schijven, die in de regel het traagste onderdeel van een computersysteem zijn. Aangezien een webapplicatie als Magento bij elke hit meer dan 7000 bestanden moet openen en inlezen, is dit een dankbaar onderwerp voor optimalisaties.

Technische uitleg

Bij elk bestand dat door een PHP-applicatie ge-include() wordt, moet gecontroleerd worden of het pad naar dat bestand wel klopt. Er kunnen namelijk punten (. of ..) in het pad gebruikt worden, en er kunnen symlinks (een soort snelkoppelingen) in staan. Kort uitgelegd: ‘.’ verwijst naar de huidige directory en ‘..’ verwijst naar de bovenliggende directory. Verder kan een symlink naar een andere directory verwijzen.

Vóórdat het bestand daadwerkelijk geopend kan worden, moeten deze verwijzingen eerst gevolgd worden: het besturingssysteem moet uitzoeken welk bestand er uiteindelijk geopend moet worden. Daarvoor wordt gebruik gemaakt van de functie realpath. Een pad naar een bestand ziet er op Linux, waar onze webservers op draaien, uit als ‘/home/users/abcdeftp/abcdefg.nl/includes/file.php‘. Om het uiteindelijke doel van het pad te vinden, moet van alle onderdelen (home, users, abcdeftp, etcetera) van het pad bekeken worden of het een verwijzing is. Bekijken of het een . of een .. is is natuurlijk simpel, maar bekijken of het een symlink is is ingewikkelder. Hiervoor wordt de systemcall lstat gebruikt. Dit is echter een relatief zware operatie, zeker omdat het zo ongelooflijk vaak gebeurt. Als er voor één hit 7000 bestanden geopend moeten worden, die opgeslagen liggen op een gemiddelde diepte van 8, dan wordt er dus 56.000 keer lstat() gedaan. Voor één hit, op één site…

Dat moet efficienter kunnen!

PHP gebruikt de door het besturingssysteem aangeboden versie van realpath(), maar kan natuurlijk ook een eigen implementatie gebruiken. Dat is exact wat wij gedaan hebben. Wij hebben de realpath() implementatie van Suhosin gepakt, en hier, op basis van een aantal aannames, een aantal slimme aanpassingen op gedaan om de hoeveelheid lstat’s te beperken. Dit heeft geleid tot de snelheidswinst die in bovenstaande grafiek af te lezen is. We hebben in ruil hiervoor wel een klein beetje functionaliteit in moeten leveren, maar hiervan werd geen gebruik gemaakt. In een volgende blogpost zal dit nog toe gelicht worden.

  • http://www.db8.nl Peter Martin

    Dat is goed nieuws!

    Behalve snelheidswinst op de server, is ook snelheidswinst te boeken door gebruik van bepaalde PHP statements.

    Hebben jullie daar algemene tips over?
    Bijv. liever “foreach” gebruiken ipv “for ($i=0, $n=count( $this->items ); $i < $n; $i++)", etc.

  • http://typofree.org Michiel Roos

    Let op!

    Ik heb zojuist een site proberen op te zetten bij BYTE. Ik ben blijkbaar een van de mensen die toch gebruik maakt van de ingeleverde functionaliteit. Ik zal hierover uitgebreid rapport uitbrengen aan de service desk.

    Het betreft een TYPO3 installatie die standaard gebruik maakt van symlinks waarmee ik problemen ondervind. Ik ga nu een nette testcase schrijven.

  • http://typofree.org Michiel Roos

    Testcase:

    Directory opzet:
    blip
    blop -> blip/ (blop is een symlink naar blip)

    File opzet in blip (en dus ook via symlink in blop):
    test.php
    ________________________________________________________________

    <?php
    require_once(‘../blop/tast.php’);
    require_once(‘/home/users/hofvbftp/hofvantwente.nl/fileadmin/blip/tast.php’);
    ?>
    ________________________________________________________________

    tast.php
    ________________________________________________________________

    <?php class tester { } ?>
    ________________________________________________________________

    Bij aanroepen http://domein.nl/blip/test.php . . .

    Verwacht resultaat: leeg scherm

    Geobserveerd resultaat: Fatal error: Cannot redeclare class tester in /home/users/bla/domein.nl/blip/tast.php on line 1

  • http://mysticletters.com Junaid

    Michiel, did you get any update on your test case? We have a typo3 installation on windows and unable to login to backend because of this error:

    Fatal error: Cannot redeclare class backend_toolbarItem in /var/www/bla/typo3/interfaces/interface.backend_toolbaritem.php on line 36

    Using default PHP 5.3 from php.net

  • http://www.byte.nl Gertjan Oude Lohuis

    Hi Junaid,
    The issue Micheal reported is indeed caused by our modifications to PHP, and we’re still seeking to solve this, without loosing the better performance.

    If you’re using the default PHP from php.net, the cause of you’re problem must be something else. We’re still using PHP 5.2(.11), not PHP 5.3.
    You say that you experience this issue on Windows? Windows doesn’t support symbolic links, which Typo3 uses in the .tar.gz-package. Furthermore, the error you supplied doesn’t look like Windows. ‘/var/www/bla/…’ is a Linux/Unix-path, not Windows.