contao/issues — Issue #626: Performance-Probleme
Author: importer
Created: 2011-11-24 15:42:31+00:00
State: open
Labels: backend, Feature

Wir betreiben neuerdings TypoLight in einer Shared-Hosting-Umgebung und die Performance ist sehr mies (9 Sekunden pro Seitenaufbau). Der Apache ist relativ stark ausgelastet (mehr als der Durchschnittliche 1&1-vroot-Server, auf dem in der Regel ja nicht viele Präsenzen laufen). Ich habe deshalb mal XDebug und KCacheGrind auf Typolight angesetzt und einige wirklich böse Performance-Bremsen entdeckt. Zwei möchte ich hier beheben (KCacheGrind-Auswertung vorher/nachher im Anhang als Screenshot).

Zunächst die Erklärung: Mir ist aufgefallen, daß Typolight insgesamt beim Seitenaufbau über 2000x is_dir() und file_exists() aufruft (obwohl das Projekt "nur" aus ca. 3000 Dateien besteht!) und dies im Shared Hosting recht teure Funktionen sind (stat-Aufrufe sollte man vermeiden). Mit KCacheGrind habe ich deshalb mal ermittelt, welche Methode die meiste Zeit beim Seitenaufbau verschwendet und siehe da: Config->getActiveModules ist für fast alle is_dir() und file_exists()-Aufrufe verantwortlich, wird ca. 46x aufgerufen und nutzt laut Profiling ca. 50% der gesamten Script-Laufdauer. Das ist wirklich viel.

Die einfachste Lösung war für mich, das Rückgabe-Ergebnis von der Methode zu cachen - den innerhalb eines Requests sollte sich daran nichts ändern (ich kenne natürlich die Semantik nicht). Das hab ich wie folgt getan:

```
public function getActiveModules()
{
static $moduleCache = NULL;

if ($moduleCache != NULL) return $moduleCache;
...
return $moduleCache = $arrActiveModules;
}
```

Dies reduzierte den Seitenaufbau von ca. 9 auf ca. 5 Sekunden. Beachtliches Ergebnis.

Weitere Zeit verschwenden die Routinen scan() und +autoload() aus functions.php - +autoload() ließe sich optimieren, indem man die Kern-Includes in der index.php einbindet. Aber das sprengt meinen Rahmen. scan() hab ich den gleichen Cache-Mechanismus wie oben verpaßt (abhängig vom Parameter natürlich).

Wenn man zusätzlich an den sinnvollen Stellen noch file_exists() und is_dir() cached, lassen sich weitere 2-3 Sekunden einsparen. Laut Profiler beträgt die Ausführungsdauer nun ca. 70% weniger Zeit.

Ich kenne den Code zu wenig, aber im Profiler sieht es so aus, als würde die Initialisierung der Anwendung am meisten Zeit brauchen, während das Rendern ein nichts dazu verbraucht im Vergleich. Wo das Seitencaching stattfindet, weiß ich nicht genau. Aber offensichtlich wird erst sehr spät in der Initialisierung überhaupt auf den Cache zugegriffen. Wenn man die Überprüfung auf den Cache weiter nach oben ziehen würde im Codepfad (sprich Seitencache ausgeben statt neu rendern), und zwar nach weit oben in die teure Initialisierungsphase, dann bietet sich sicher noch ein enormes Einsparpotential. Aber auch das sprengt meinen dafür gesetzten Rahmen.

Ich habe den Seitenaufbau jetzt von ca. 9 auf 2-3 Sekunden runteroptimiert - immer noch sehr langsam. Eine Idee wäre, die Anwendungs-Initialisierung im Shared Memory oder in Memcached zu cachen - aber ich kenne den Code zu wenig, um dort anzusetzen.

Jedenfalls ist meine optimierte Version auf dem Shared-Hosting-Server jetzt nur unwesentlich langsamer als die unoptimierte Version auf einem dedizierten Server der sogar mehr Speicher und CPU hat.

Mit diesen Infos findet jemand, der den Code kennt, sicher noch andere Optimierungspunkte.

[Download the attachments](http://www.contao.org/tl_files/tickets/626.zip "Download the attachments of this ticket")

--- _Originally created by hurikhan77 on March 28th, 2009, at 12:50pm (ID 626)_