TYPO3 Performance: So geht’s schneller!

TYPO3 Performance: So geht’s schneller!

Die Perfomance einer TYPO3-Website zu verbessern, gehört wohl zu den wichtigsten Anforderungen in jedem Projekt. Grundsätzlich sieht es allerdings so aus, dass du beliebig viel (oder wenig) Zeit in die TYPO3 Performance-Optimierung investieren kannst. Miss den Aufwand daher immer daran, welche Verbesserung er dir oder deinen Kunden bringt.


Kurzer Hinweis: Dieser Blogbeitrag ist eine aktualisierte Version. Basis ist der Blogbeitrag von Guido Schmechel vom 2. Oktober 2015 unter gleichnamigem Titel. 


Es gibt im Netz viele (veraltete) Standardtipps für TYPO3-Projekte, z.B. „entfernt Extensions mit $GLOBALS['TSFE']>noCache() = 1„. Das kennst du hoffentlich bereits. Hier unsere Empfehlungen, die wir aus Erfahrungen in Dutzenden Projekten gesammelt haben.

Messwerte

Statt direkt Lasttests durchzuführen, solltest du erstmal einfache Ladezeiten ermitteln.

  1. Die einfachste Möglichkeit sind die Entwicklertools des Browsers. Dort kannst du im Reiter Netzwerkanalyse die Ladezeiten ermitteln. Relevant sind natürlich „Time to first byte“ und das Laden aller Resourcen. Achte darauf, dass im Reiter die Option „Caches deaktivieren“ / „Disable Caches“ gewählt ist. Schließlich wollen wir die Performance nicht anhand von lokal gespeicherten Dateien ermitteln.
  2. Lass dir die Werte im TYPO3 AdminPanel ausgeben. Pro Seite sollte man sich 5-10 Zugriffszeiten betrachten, um einen guten Schnitt zu erhalten.
    Hinweis: Dies findet auf einem Stagingsystem statt, wo deine Zeiten nicht groß von außen beeinflusst werden.
    Mit dem Adminpanel findest du heraus, ob auf einer Seite noch ungecachte Elemente (COA_INT oder USER_INT) vorhanden sind. Das Adminpanel wird mit folgendem TypoScript im Setup aktiviert: config.admPanel = 1
  3. Auch die unten genannten Online-Tools (PageSpeed, GTMetrix) geben einen ersten Eindruck zur Leistung.

Erst im nächsten Schritt solltest du Lasttests in Erwägung ziehen, um weitere Schwachstellen auszumachen. Dazu raten wir denen, die genug Zeit und Ressourcen investieren können.

PageSpeed Insights Screenshot
Screenshot aus PageSpeed Insights (Google Developers)

Frontend-Standards

Mit Tools wie GTMetrix oder Google Page Speed wird ganz gut aufgezeigt, was im Frontend nicht rund läuft. Die Klassiker sind hier oft folgende Dinge:

  • Fehlerhaft eingestelltes Caching
  • Schlecht komprimierte Bilder
  • Kein GZIP aktiviert

Diese Dinge sollte man erst einmal beheben, wenn sie auftreten. Eine gute .htaccess reicht dort oft aus. Diese kompletten Punkte hat die Marit AG auf den TYPO3 Developer Days 2015 vorgestellt. Die Slides kann man sich hier ansehen.

Kernpunkte in der Umsetzung:

  • Sinnvoll komprimierte Bilddateien – unser empfohlener Wert in der LocalConfiguration.php:
    [GFX][jpg_quality] = 80
  • Komprimierte JavaScript- und CSS-Resourcen mehrere Optionen:
    • Grunt / Gulp etc.
    • Auslieferung per CDN
  • Browser Caching in TypoScript aktiviert:
    config.sendCacheHeaders = 1
    config.enableContentLengthHeader = 1
  • Above the fold: Was soll schnell sichtbar sein, warum ist das so wichtig und wie wird es umgesetzt?
    • Ein Thema für die Frontend-Entwickler und Screendesigner
    • Hier wirken die Ladereihenfolge der Frontend-Assets und Bilder
    • Fast immer lohnt sich das Nachladen der Bilder per Lazy Loading; z.B. mit Unveil, verlok/lazyload oder mit der Lib deiner Wahl.

Die Generierung der Frontent-Assets per Grunt sollte mittlerweile Standard sein. Wir empfehlen das uneingeschränkt. Es ist erst eine Hürde, auf Grunt umzustellen, aber es hat später den Vorteil, dass sich die Komprimierung der Assets danach in TYPO3 ausschalten lässt. Damit haben wir den ersten Performancegewinn.

Menü

Früher war das TYPO3 Menü ein großes Problem in Sachen Performance. Es wurde in der Regel per TypoScript generiert und sorgte bei ungecachten Seiten für Ladezeitverlängerungen. Pro Seitenaufruf wird hier auch entsprechend abgerufen, ob jemand eingeloggt ist, wie der Status der Seite ist, und natürlich muss auch der Link generiert werden. Wer TYPO3 7.6 und darunter nutzt, ist auf ein TypoScript-Menu angewiesen. Hier sollte man versuchen, dass Menu in ein COA-Objekt auszulagern, so dass es seitenweit gecacht werden kann. Ein Gist / Snippet dazu finden wir bei Philipp Gampe: menu.ts – Fully cached menu with TypoScript.

Ab TYPO3 8.x bringt der Umstieg auf Menugenerierung per Fluidtemplate und dem MenuProcessor eine Menge mehr, das Caching und damit die Auslieferung wurde hier stark optimiert.

Code

Screenshot eines Fluid-Templates
Dieses Fluid-Template könnte mit weniger Kontrollstrukturen mehr leisten 🙂

Fluid
Schau genauer in deine Fluid-Templates. Es lohnt sich meist, sich wiederholende Kontrollstrukturen, String- oder Linkgenerierungen ins Model oder in den Controller auszulagern. Dazu gibt es keine pauschale Ausage, aber ein Refactoring nach einer gewissen Zeit ist immer sinnvoll – man bekommt einen anderen Blick auf die Dinge.

Extbase / PHP
Die wenigsten Plugins bzw. Actions müssen heute noch als non-cacheable definiert werden. Wenn du eigene Extensions hast: Geh durch deine ext_localconf.php und kontrolliere, welche Actions aus dem Abschnitt non-cacheable actions entfernen werden können.

Datenbank

Ein Flaschenhals bei vielen Hostern ist die Verbindung zur Datenbank. Eine Datenarchitektur mit vielen Relationen kann die Anzahl der Datenbankabfragen pro Seite in die Hunderte treiben. Als ersten Schritt sollte man für alle oft abgefragten Tabellenfelder Indexe setzen.

Ein Beispiel für die sys_file_reference, womit wir gute Erfahrung gemacht haben:

CREATE TABLE sys_file_reference (
KEY sorting (tablenames,uid_foreign,fieldname,sorting_foreign),
);

Besonders bei eigenen Tabellen hilft es, die Indexe zu setzen, so dass MySQL nicht bei jeder Suche die ganze Tabelle durchsuchen muss.
Die Felder im Index something_list sind hier diejenigen, die in diesem über das Repository abgefragt werden, z.B. in der Listenansicht:

CREATE TABLE tx_myextension_domain_model_something (

uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,

headline varchar(255) DEFAULT '' NOT NULL,
content text,
address text,
email varchar(255) DEFAULT '' NOT NULL,
www varchar(255) DEFAULT '' NOT NULL,
photo int(11) unsigned NOT NULL default '0',
categories int(11) unsigned DEFAULT '0' NOT NULL,

--TYPO3-Standardfelder hidden, timestamp--

starttime int(11) unsigned DEFAULT '0' NOT NULL,
endtime int(11) unsigned DEFAULT '0' NOT NULL,

--TYPO3-Standardfelder Versionierung, Sprache etc.--

PRIMARY KEY (uid),
KEY t3ver_oid (t3ver_oid,t3ver_wsid),
KEY language (l10n_parent,sys_language_uid),
KEY something_list (headline(64), content(255), address(64), starttime, endtime)
);

Dieser Key spart uns wertvolle Zeit auf Startseiten und Listenansichten.

Server

Auch, wenn es vielleicht nicht dein Fachgebiet ist; es kann nicht schaden, sich mal die Apache/nginx/PHP/MySQL-Einstellungen genauer anzusehen. Oder lasst es von deinem netten Fachkollegen tun.

  • Der Umstieg von PHP 5.4 zu PHP 5.6 brachte früher schon 10% Gewinn ein,
  • Ein Vergleich zwischen PHP 5.5 und PHP 7.0 zeigt, dass die Seiten bis 40% schneller aufgebaut werden. (Quelle: pagemachine.de)

Caching

Wir hatten vor längerer Zeit Helmut Hummel im Haus und diskutierten auch Caching-System, die TYPO3 unterstützt. Wir versuchten es dann erst mit Memcached und später mit Redis. Wir können hier sagen: Dieser Sprung ist beachtlich.

Leider sind wir durch diese Entscheidung zunächst tief gefallen. Bei unserer komplexen Modelstruktur wirde der extbase_reflection_cache sehr groß. Dadurch dass Seiten teilweise nur noch in 7-8 Sekunden geladen. Unsere aktuelle Lösung: Cache-Konfiguration optimieren. Das sieht so aus und klappt für diesen Fall bestens:

if (class_exists('redis')) {
   /** Database numbers 0 and 1 are used and flushed by the core unit tests and should not be used if possible. */
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pages']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pages']['options'] = array('defaultLifetime' => 3600, 'database' => 2);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pagesection']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pagesection']['options'] = array('defaultLifetime' => 3600, 'database' => 3);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_hash']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_hash']['options'] = array('defaultLifetime' => 3600, 'database' => 4);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_rootline']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_rootline']['options'] = array('defaultLifetime' => 3600, 'database' => 5);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_object']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_object']['options'] = array('defaultLifetime' => 3600, 'database' => 6);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_reflection']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_reflection']['options'] = array('defaultLifetime' => 3600, 'database' => 7);

   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_datamapfactory_datamap']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\RedisBackend';
   $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['extbase_datamapfactory_datamap']['options'] = array('defaultLifetime' => 3600, 'database' => 8);
}

Über die defaultLifetime kann man natürlich diskutieren.
Wichtig ist, dass auch der TYPO3 Scheduler Job zum Cache-Aufräumen integriert ist.

Mehr wichtige Infos dazu in den TYPO3 Docs zum Caching Framework.

Performance Optimierung – was geht noch?


Staticfilecache
Für die meisten Projekte lohnt es, sich die Extension Staticfilecache genauer anzusehen. Das ist Tim Lochmüllers Fork der beliebten Extension nc_staticfilecache (die nicht mehr weiterentwickelt wird). Sie speichert Seiten als statische Dateien im typo3temp-Verzeichnis und leitet durch clevere htaccess-Rewrite-Regeln darauf weiter, sofern der Cache nicht abgelaufen ist. Das ist äußerst effektiv und ermöglicht sensationelle Ladezeiten von unter 0,5 Sekunden (TTFB).

Screenshot: Staticfilecache-Informationen im TYPO3-Backend
Staticfilecache-Informationen im TYPO3-Backend

Schön ist auch, dass wir in der aktuellen Version von Staticfilecache im Backend über das Info-Modul eine Übersicht über die statisch gecachten Seiten erhalten und darüber, was einem Caching im Weg steht (COA_INT-Objekte, config.no_cache etc.).

Varnish Cache
Falls es dein Hosting zulässt: TYPO3 lässt sich gut mit einem Varnish Cache verbinden. Eine gute Konfiguration zeigt euch Oliver Thiele in diesen Slides vom TYPO3Camp München. Zu empfehlen ist auch die Extension Varnish Connector. Sie informiert den Varnish Proxy über TYPO3-Parameter und Gültigkeit des Caches, damit er die richtige Caching-Entscheidungen treffen kann.


TYPO3 Entwickler gesucht

Neueinstieg oder neue Destination gesucht? Wir freuen uns über neue Kolleg/innen in Köln, die mit uns an der TYPO3 Performance schrauben. Hier geht’s zu unserem Job Posting.


Fazit

TYPO3 Performance-Optimierung ist in der Regel eine Sammlung vieler kleiner Maßnahmen. Man arbeitet sich dabei von außen (dem Frontend) bis nach innen (Datenbank-Zugriff) vor. Unserer Erfahrung nach kommt der größte Sprung bei den Ladezeiten mit den Caching-Systemen.

Wir freuen uns über dein Feedback. Denn man kann ja immer noch mehr aus seinem Projekt rausholen. Wenn du mehr zu den Arbeiten erfahren möchtest, kannst du gerne unser Kontaktformular nutzen oder eine E-Mail an martin.terber[at]ppw.de schreiben.

Mehr zu unserer TYPO3 Arbeit: TYPO3 Agentur Köln + Münster


Weitere PPW Blogbeiträge, die dich interessieren könnten:

TYPO3-Awards für Red Dot Website

Strukturierte Daten mit schema.org – ausgezeichnete Snippets

Rector: PHP-Code Refactoring mit Autopilot