Typo3, PHP, libc, Kernel, CPU, Problem?
März 12, 2010 – 21:17Ich habe eben die letzen paar Stunden damit verbracht herauszufinden, warum das laden einer bestimmten Typo3 Präsenz immer mindestens 10 Sekunden dauert. Das Ganze begann nach dem Umzug auf einen neuen Server, ohne jegliche Änderung an der Typo3 Installation oder der verwendeten PHP Version.
Im Admin Panel war zu erkennen, dass in dem Schritt ‘Front End user initialized’ die gesamte Zeit verloren ging. Leider konnte ich über Typo3 das ganze nicht weiter aufschlüsseln, sodass ich mich daran machte Debug Kommentare in den Sourcecode einzubauen. Nach etlichen Reloads der Seite hatte ich es geschafft das Ganze Problem auf die PHP Funktion uniqid(), welche zur Erzeugung einer eindeutigen SessionID innerhalb von Typo3 verwendet wird einzugrenzen.
Aus dem Typo3 Problem wurde somit ein PHP Problem. Etwas Googlen brachte zu Tage, dass andere das Problem auch kennen und die PHP Entwickler der Meinung sind, dass es kein Bug sei.Dennoch habe ich ein kleines Testskript verfasst, welches uniqid() ausführt und siehe da: manchmal ging es ruckzuck, manchmal (etwa jeden fünften Aufruf) brauchte es 10 Sekunden.
uniquid() verwendet unter Linux intern die Userspace Funktion usleep() der glibc. Für diese Funktion gibt es auch ein Äquvivalent auf der Kommandozeile. Der Aufruf von ‘usleep 1′ sollte eigentlich nur 1 usec andauern, bei mir blieb er ab und zu allerdings bis zu 10 Sekunden beschäftigt, eben analog zu der PHP Funktion in meinem Testskript.
Also ein Problem der libc? Daran mochte ich nicht glauben. Abgesehen davon, dass die Funktion als deprecated gekennzeichnet ist, ist sie doch schon recht lange präsent und von zentraler Verwendung – ein Bug erschien mir nicht sehr naheliegend.
Weiteres Googeln brachte mich zum Kernel und seinen verschiednen Clocksources. Der Linuxkernel bietet im Allgemeinen drei mögliche Quellen für 32Bit Systeme an: HPET, TSC und PIT. Die installierte CentOS 5.4 Distribution selektiert beim Booten automatisch TSC als Clocksource, weil diese performant und zuverlässig ist. Leider funktioniert diese nicht so sehr zuverlässig mit AMD Prozessoren, was eine kleine Recherche im Internet zu Tage brachte. Es gibt von AMD einen kleinen Artikel (allerdings zu RHEL4) bezüglich dieses Problems.
Darin wird beschrieben, dass es bei K8 Kernen zu Problemen mit dem Powermanagement und TSC kommt, da die CPU Taktrate variiert und TSC auf Basis dieser arbeitet. Bei SMP soll es wohl auch Probleme mit TSC und K8 Kernen geben. Das Ganze hat nicht zu 100% auf mein Szenario gepasst, schließlich habe ich CentOS 5.4 (analog RHEL 5.4) im Einsatz und eine Opteron 1212 HE CPU ohne erkennbares Powermanagement, aber ich dachte ein Versuch schadet nicht.
In meinem ersten Schritt habe ich notsc als Kernelparameter angefügt und rebootet. Leider hatte das nicht den gewünschten Effekt. Der Kernel wurde mit der Option CONFIG_X86_TSC kompiliert, weshalb sich tsc laut dmesg nicht abschalten ließ. In meinem zweiten Versuch habe ich notsc durch hpet ersetzt. hpet ist die nicht so performante Clocksource Alternative. Da der Server nun nicht unter enormer Last steht sehe ich hier aber kein großes Problem.
Nach dem Reboot konnte ich erfreut feststellen, dass mein Problem verschwunden war. usleep, wie auch uniqid() funktionierten wieder in einer normalen Geschwindigkeit und auch die Website reagiert nun wieder akzeptabel schnell.
Wer ein ähnliches Verhalten feststellt (uniqid() oder usleep() ist langsam, Typo3 benötigt lange die SessionID zu erzeugen) und eine AMD CPU hat sollte mal Versuchen ‘hpet’ an die Kerneloptionen anzuhängen. Vielleicht hilft es ja.