Performance
shikiphp führt echtes TextMate-Tokenizing in reinem PHP durch. Deshalb lohnt es sich, ehrlich zu sagen, was schnell ist und was nicht.
Was dich erwartet
Rechne pro Datei mit Dutzenden bis Hunderten Millisekunden, nicht mit Mikrosekunden. Der Tokenizer speichert kompilierte Regeln und Scanner zwischen. Grammatiken werden verzögert geladen (ein Beispiel, das keine eingebettete Sprache nutzt, muss sie nicht dekodieren). Die meisten Grammatikmuster laufen über natives preg_* in einem auf Äquivalenz geprüften PCRE-Schnellpfad; für den Rest kommt der Matcher in reinem PHP zum Einsatz (siehe Architektur).
Das sind Messwerte für wiederholte Einzelaufrufe aus dem Benchmark des Repositorys
(bench/bench.php, Theme github-dark) auf einem Rechner, bei Korpusdateien mit
etwa 55 bis 105 Zeilen:
| Grammatik | PHP 8.2 | PHP 8.4 |
|---|---|---|
| JSON, YAML | 30–65 ms | 25–45 ms |
| CSS, HTML | 100–120 ms | 80–100 ms |
| Python, Rust, Go, Bash, Markdown | 190–220 ms | 125–175 ms |
| PHP | etwa 290 ms | etwa 170 ms |
| TypeScript, TSX | 490–510 ms | 310–370 ms |
Beim ersten Aufruf einer Sprache in einem Prozess fallen außerdem einmalig Kosten für das Laden und Kompilieren der Grammatik an: In denselben Läufen waren es 50–70 ms für JSON und etwas mehr als eine Sekunde für Markdown. Der Aufwand steigt mit der Komplexität der Grammatik und der Eingabegröße. Die Werte hängen von der Hardware ab, miss also auf deinem eigenen System: Klone das Repository und führe composer install und anschließend composer bench aus.
Sicherheitsvorkehrungen
Die Regex-Engine schützt vor ReDoS und merkt sich Fehlschläge, damit problematische Muster langsamer werden, statt zu hängen. Mit tokenizeMaxLineLength kannst du außerdem den Aufwand pro Zeile begrenzen. Bei Zeilen ab einer bestimmten Länge wird dann ein einzelnes Plain-Token ausgegeben — als Schutz vor gezielt präparierten einzeiligen Eingaben.
Caching in der Produktion
Am zuverlässigsten hältst du die Hervorhebung aus dem Request-Pfad heraus, indem du sie nicht bei jeder Anfrage ausführst. Derselbe Code mit denselben Optionen ergibt immer dasselbe HTML und lässt sich daher perfekt cachen:
- Hebe Code für statische Websites und Dokumentation beim Build hervor.
- Cache das gerenderte HTML (mit Code und Optionen als Schlüssel) für vom Nutzer bereitgestellte oder in einer Datenbank gespeicherte Snippets und verwende es erneut, bis sich der Quelltext ändert.
Verwende innerhalb eines Prozesses dieselbe Highlighter-Instanz wieder (die Shikiphp-Fassade übernimmt das für dich), damit Grammatik- und Theme-Caches über Aufrufe hinweg gemeinsam genutzt werden.