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.


Weitere PPW Blogbeitr├Ąge, die dich interessieren k├Ânnten:

Strukturierte Daten mit schema.org – ausgezeichnete Snippets

Nachlese zum TYPO3 Camp RheinRuhr

TYPO3-Awards f├╝r Red Dot Website