Magento-Profiling mit Blackfire und Xhprof
60fps
ms
Engineering · Profiling · Performance · Magento 2
Magento-Profiling mit Blackfire und Xhprof
Hot Paths finden, bevor sie den Checkout ausbremsen

Wer Magento-Performance-Probleme nur durch Vermutungen angeht, verschwendet Zeit an den falschen Stellen. Dieser Artikel zeigt, wie Blackfire, Xhprof beziehungsweise Tideways sowie der eingebaute Magento Profiler eingesetzt werden, um Flame Graphs zu lesen, langsame Observer und Plugins zu identifizieren und Profile sauber zu vergleichen, auch produktiv mit sicherem Sampling.

18 Min. Lesezeit Blackfire · Xhprof · Tideways Magento 2.4.8 · Flame Graphs · Sampling

1. Warum systematisches Profiling und nicht Raten

Der häufigste Fehler bei Magento-Performance-Problemen: Ein Entwickler vermutet die Ursache anhand von Bauchgefühl, optimiert eine vermeintlich teure Stelle im Code und wundert sich anschließend, warum die Antwortzeit kaum besser wird. Ohne Messung bleibt jede Optimierung ein Ratespiel, denn die tatsächlich teuersten Codepfade in Magento liegen selten dort, wo man sie intuitiv vermutet, etwa in tief verschachtelten Plugin-Ketten, in Observern, die bei jedem Seitenaufruf feuern, oder in Template-Loops, die pro Produkt einen zusätzlichen DB-Query auslösen.

Profiling macht diese Kosten sichtbar, indem es jeden Funktionsaufruf mit Zeit, Speicherverbrauch und Aufrufhäufigkeit protokolliert. Statt zu fragen „Was könnte langsam sein?“ liefert ein Profiler die Antwort auf „Was ist tatsächlich langsam, und wie oft wird es aufgerufen?“. Gerade in gewachsenen Magento-Installationen mit vielen Drittanbieter-Modulen ist das der einzige verlässliche Weg, um zwischen Kernsystem, Plugins und individuellem Code zu unterscheiden und die Optimierung dort anzusetzen, wo sie den größten Effekt auf die Gesamtlaufzeit hat.

2. Profiling-Werkzeuge im Überblick

Für Magento kommen im Wesentlichen vier Werkzeugklassen infrage, die sich in Overhead, Produktionstauglichkeit und Granularität deutlich unterscheiden. Blackfire ist ein kommerzielles SaaS-Profiling-Tool mit einer PHP-Probe und einem lokalen Agent, das detaillierte Call Graphs inklusive I/O- und SQL-Zeiten liefert und sich über eine Web-Oberfläche vergleichen lässt. Xhprof, ursprünglich von Facebook entwickelt, und dessen aktiv gepflegter Nachfolger Tideways messen ähnliche Daten als PHP-Extension mit sehr geringem Overhead und eignen sich besonders für dauerhaftes Sampling.

Magentos eigener Magento\Framework\Profiler ist ein Timer-basiertes Bordmittel ohne externe Abhängigkeiten, ideal für schnelle Ad-hoc-Analysen direkt im Dev-Setup. Ergänzend hilft der Query Log von MySQL beim Aufspüren einzelner N+1-Query-Probleme, liefert aber keine PHP-seitige Zeitverteilung. In der Praxis ergänzen sich die Werkzeuge: Blackfire und Xhprof/Tideways für tiefe Call-Graph-Analysen, der Magento Profiler für schnelle lokale Checks, der Query Log als punktuelles Diagnosewerkzeug.

3. Blackfire Probe und Agent im Dev-Setup einrichten

Blackfire besteht aus zwei Komponenten: einer PHP-Probe, die als Extension im PHP-Container läuft und Messdaten sammelt, und einem Agent, der diese Daten bündelt und verschlüsselt an die Blackfire-Cloud überträgt. Im Mark-Shust-Docker-Setup wird die Probe direkt im PHP-FPM-Container installiert, danach müssen Server-ID, Server-Token sowie Client-ID und Client-Token aus dem Blackfire-Dashboard eingetragen werden, damit lokale Profile dem richtigen Projekt zugeordnet werden.

Nach einem Neustart von PHP-FPM lässt sich ein einzelner Request gezielt profilieren, indem man ihn mit blackfire curl statt mit einem normalen HTTP-Client aufruft, oder über die Browser-Extension direkt im laufenden Shop. Für CLI-Kommandos wie Indexer-Läufe oder Cron-Jobs funktioniert das Voranstellen von blackfire run genauso zuverlässig und ist besonders hilfreich, wenn ein Reindex nach einem Deployment plötzlich deutlich länger dauert als erwartet.


# Install Blackfire probe and agent inside the Magento PHP container (Mark Shust setup)
bin/cli bash -c "curl -sS https://get.blackfire.io/blackfire.gpg | apt-key add - \
  && echo 'deb http://packages.blackfire.io/debian any main' > /etc/apt/sources.list.d/blackfire.list \
  && apt-get update && apt-get install -y blackfire-php blackfire-agent"

# Register the environment credentials from the Blackfire dashboard
bin/cli blackfire-agent -config /etc/blackfire/agent.toml -server-id="<server-id>" -server-token="<server-token>"
bin/cli blackfire-php-config --client-id="<client-id>" --client-token="<client-token>"

# Restart PHP-FPM so the probe extension gets loaded
bin/restart

# Profile a single request through the Blackfire agent instead of a plain HTTP client
bin/cli blackfire curl https://mironsoft.test/catalogsearch/result/?q=shirt

# Profile a CLI command, e.g. a reindex run that got slow after a deployment
bin/cli blackfire run php bin/magento indexer:reindex catalog_category_product

4. Xhprof und Tideways konfigurieren

Tideways bringt eine moderne, aktiv gepflegte Xhprof-kompatible Extension mit, die sich per ini-Datei aktivieren lässt und im Gegensatz zu klassischem Xhprof auch produktionstaugliches Sampling unterstützt. Zentrale Stellschraube ist tideways.sample_rate: Der Wert 0 deaktiviert automatisches Sampling und erlaubt gezieltes manuelles Profiling einzelner Requests, während ein Wert größer 0 einen festen Prozentsatz aller Requests automatisch aufzeichnet, ohne dass Entwickler eingreifen müssen.

Für lokale Debugging-Sessions reicht es, die Extension mit deaktiviertem Sampling zu laden und Profile gezielt über die Tideways-Bibliothek oder direkt über xhprof_enable()/xhprof_disable() zu starten und zu stoppen. Die aufgezeichneten Rohdaten liegen als serialisiertes PHP-Array vor und lassen sich entweder in die Tideways-Cloud hochladen oder mit einem lokalen Callgraph-Viewer wie xhprof-viewer visualisieren, was besonders bei Umgebungen ohne Internetzugang hilfreich ist.


# Enable the Tideways xhprof-compatible extension in the PHP container
bin/cli bash -c "cat <<'EOF' > /usr/local/etc/php/conf.d/zzz-tideways.ini
extension=tideways_xhprof.so
tideways.sample_rate=0
tideways.auto_prepend_library=0
tideways.connection=tcp://127.0.0.1:9135
EOF"

# Reload PHP-FPM to pick up the new extension
bin/restart

# Confirm the extension is loaded and ready
bin/cli php -m | grep tideways

5. Der eingebaute Magento Profiler

Neben externen Tools bringt Magento mit Magento\Framework\Profiler ein eigenes, leichtgewichtiges Timer-System mit, das an strategischen Stellen im Framework bereits Messpunkte gesetzt hat, etwa um Controller-Dispatch, Layout-Generierung und Block-Rendering einzeln auszuweisen. Aktiviert wird der Profiler über die Umgebungsvariable MAGE_PROFILER, deren Wert das Ausgabeformat bestimmt: html erzeugt einen aufklappbaren Baum aller Timer inklusive kumulierter Zeit und Aufrufanzahl, csvfile schreibt maschinenlesbare Daten für automatisierte Auswertung.

Der große Vorteil gegenüber Blackfire oder Xhprof: kein zusätzliches Extension-Setup nötig, der Profiler ist Teil des Frameworks und funktioniert sofort in jedem Dev-Container. Der Nachteil: Er misst nur Codepfade, an denen explizit \Magento\Framework\Profiler::start()/::stop()-Aufrufe gesetzt wurden, deckt also nicht automatisch jede Funktion ab wie ein vollständiger Call-Graph-Profiler. Für eigene Module lassen sich zusätzliche Timer einfach selbst ergänzen, um gezielt einen verdächtigen Codeabschnitt zu isolieren.


# Enable Magento's built-in Framework\Profiler for a single CLI run
MAGE_PROFILER=html bin/magento indexer:reindex catalog_category_product

# The HTML profiler report is written next to the project root
ls -la src/var/log/profiler.html

# Enable it for regular web requests via the deployment configuration
bin/magento config:set dev/debug/profiler_type html

# Or trigger it ad-hoc for a single CLI command without touching persisted config
bin/cli bash -c "MAGE_PROFILER=html php bin/magento cache:status"

6. Flame Graphs und Call Graphs richtig lesen

Ein Flame Graph stellt den Aufrufstapel als gestapelte horizontale Balken dar: Die x-Achse repräsentiert nicht die Zeit im klassischen Sinn, sondern die relative Breite der im jeweiligen Funktionsaufruf verbrachten Zeit, die y-Achse die Aufruftiefe. Je breiter ein Balken, desto mehr Gesamtzeit wurde in dieser Funktion und ihren Unterfunktionen verbracht, unabhängig davon, wie oft sie aufgerufen wurde. Breite, flache Balken weit oben im Graph sind fast immer die lohnendsten Optimierungsziele.

Blackfire stellt zusätzlich einen Call Graph bereit, der Funktionen als Knoten und Aufrufe als gerichtete Kanten mit exklusiver und inklusiver Zeit sowie Aufrufanzahl darstellt. Wichtig ist die Unterscheidung zwischen exklusiver Zeit (nur die Funktion selbst, ohne Unterfunktionen) und inklusiver Zeit (Funktion plus alle aufgerufenen Unterfunktionen): Eine Funktion mit hoher inklusiver, aber niedriger exklusiver Zeit ist meist nur ein Verteiler, während hohe exklusive Zeit auf tatsächlich teuren eigenen Code hinweist, etwa eine ineffiziente Schleife oder eine fehlende Query-Optimierung.

7. Hot Paths identifizieren: Observer, Plugins, Templates

In Magento konzentrieren sich Performance-Probleme typischerweise auf drei Stellen: Event-Observer, die bei jedem save oder load eines Modells feuern und dabei unbemerkt zusätzliche DB-Queries oder externe API-Aufrufe auslösen; Plugins, die als around-Interceptor die eigentliche Methode umschließen und bei falscher Implementierung den kompletten Call-Stack darunter verdoppeln; und Templates, die in Schleifen pro Produkt oder Kategorie zusätzliche Repository-Aufrufe absetzen, statt Daten vorab gesammelt zu laden. Im Flame Graph erscheinen solche Hot Paths als breite, sich wiederholende Muster mit auffällig vielen Aufrufen derselben Methode.

Ein bewährtes Vorgehen: Zunächst im Flame Graph nach den breitesten Balken unterhalb von Magento\Framework\Event\Manager::dispatch oder Magento\Framework\Interception\Interceptor suchen, dann per Klick auf den betroffenen Knoten gezielt in die Aufrufkette hineinzoomen. Für punktuelles manuelles Profiling einzelner Verdachtsstellen lässt sich ein Observer oder Plugin temporär mit xhprof_enable()/xhprof_disable() umschließen, um dessen Kosten isoliert von der übrigen Anfrage zu messen, ohne ein komplettes Request-Profil erzeugen zu müssen.


<?php
declare(strict_types=1);

namespace Mironsoft\Performance\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

/**
 * Wraps a suspected slow observer with a manual xhprof measurement window.
 * Only intended for temporary local debugging, never for production code.
 */
class ProfiledStockUpdateObserver implements ObserverInterface
{
    /**
     * Executes the original observer logic inside an isolated profiling window.
     *
     * @param EventObserver $observer
     * @return void
     */
    public function execute(EventObserver $observer): void
    {
        // Start a dedicated xhprof measurement just for this observer
        xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);

        $this->runOriginalLogic($observer);

        $data = xhprof_disable();
        file_put_contents(
            '/tmp/xhprof/stock_update_' . microtime(true) . '.xhprof',
            serialize($data)
        );
    }

    /**
     * Placeholder for the actual observer logic under investigation.
     *
     * @param EventObserver $observer
     * @return void
     */
    private function runOriginalLogic(EventObserver $observer): void
    {
        // Original stock recalculation logic lives here
    }
}

8. Vorher/Nachher-Profile sauber vergleichen

Eine einzelne Profiling-Session zeigt nur eine Momentaufnahme, die durch Caching-Zustand, Serverlast oder zufällige Netzwerklatenz verzerrt sein kann. Belastbare Aussagen entstehen erst durch den Vergleich mehrerer Profile unter identischen Bedingungen: gleiche Testdaten, gleicher Warm-up-Zustand des Caches, mehrere Wiederholungen statt einer Einzelmessung. Blackfire bietet dafür die eingebaute Vergleichsfunktion, die zwei Profile nebeneinander mit farblich markierten Deltas pro Funktion darstellt, inklusive Prozentangabe der Verbesserung oder Verschlechterung.

Bei Xhprof/Tideways-Rohdaten übernimmt diese Aufgabe ein Diff-Tool, das zwei serialisierte Profile einliest und pro Funktion die Differenz aus Aufrufzeit, Aufrufanzahl und Speicherverbrauch berechnet. Entscheidend ist, nicht nur die Gesamtlaufzeit zu vergleichen, sondern auch die Aufrufanzahl einzelner Funktionen: Sinkt die Gesamtzeit einer Funktion, weil sie seltener aufgerufen wird statt weil sie selbst schneller geworden ist, deutet das auf eine strukturelle statt eine algorithmische Verbesserung hin, was für die Bewertung der eigentlichen Fix-Ursache relevant ist.

9. Sicheres Profiling in Produktion mit Sampling

Vollständiges Profiling jedes einzelnen Requests ist in Produktion nicht praktikabel: Der Overhead von Xhprof-artigen Extensions liegt zwar niedrig, summiert sich aber bei hoher Anfragefrequenz spürbar auf, und Blackfires vollständiger Call Graph erzeugt zusätzlichen I/O-Overhead durch die Datenübertragung an den Agent. Die Lösung heißt Sampling: Nur ein kleiner, zufällig oder gezielt ausgewählter Prozentsatz der Requests wird tatsächlich profiliert, etwa ein bis fünf Prozent, während der Rest ganz normal ohne Messaufwand läuft.

Tideways unterstützt automatisches Sampling nativ über tideways.sample_rate, Blackfire lässt sich über einen Trigger-Header oder die Kombination mit einer eigenen Middleware gezielt für einzelne Requests aktivieren, etwa nur für Requests mit besonders hoher Antwortzeit oberhalb eines Schwellenwerts. Wichtig für den produktiven Einsatz: Health-Check-Endpunkte und statische Assets sollten grundsätzlich von der Profilierung ausgeschlossen werden, da sie das Bild verzerren, ohne relevante Erkenntnisse zu liefern, und ein Rate-Limit verhindert, dass ein plötzlicher Traffic-Spike den Agent oder das Speichersystem überlastet.


{
  "sampling": {
    "enabled": true,
    "rate": 0.01,
    "trigger_header": "X-Blackfire-Sample",
    "exclude_paths": [
      "/health-check",
      "/media/*",
      "/static/*"
    ],
    "max_profiles_per_hour": 120,
    "environments": ["production"]
  },
  "alert_thresholds": {
    "wall_time_ms": 800,
    "sql_queries": 40,
    "memory_mb": 128
  }
}

Werkzeugvergleich

Die folgende Übersicht fasst zusammen, wann welches Profiling-Werkzeug den größten Nutzen bringt, gemessen an Overhead, Produktionstauglichkeit und Granularität der Messdaten.

Werkzeug Overhead Produktionstauglich Typischer Einsatz
Blackfire Gering (ca. 2-5 %) Ja, mit Sampling/Trigger Gezieltes Deep-Dive-Debugging
Xhprof / Tideways Sehr gering (< 2 %) Ja, dauerhaft aktivierbar Kontinuierliches Monitoring
Magento Profiler Mittel bis hoch Nein, nur Debug-Modus Schnelle Ad-hoc-Analyse lokal
Query Log Hoch bei aktivem Logging Nein Einzelne N+1-Query-Probleme finden

In der Praxis ergänzen sich die Werkzeuge statt sich gegenseitig zu ersetzen: Xhprof/Tideways mit niedrigem Sampling-Rate läuft dauerhaft in Produktion mit und liefert Frühwarnsignale, Blackfire kommt gezielt bei tieferen Untersuchungen einzelner Requests zum Einsatz, und der Magento Profiler bleibt das schnellste Werkzeug für einen ersten lokalen Check, bevor überhaupt eine externe Extension installiert wird.

Mironsoft

Profiling, Performance-Debugging und Hyvä-Optimierung für Magento-Shops

Hot Paths im eigenen Shop finden?

Wir richten Blackfire und Xhprof/Tideways in eurem Dev- und Produktionssetup ein, lesen die Flame Graphs für euch und setzen die identifizierten Optimierungen direkt in Magento- und Hyvä-Code um.

Profiling-Setup

Blackfire Probe/Agent und Xhprof/Tideways in Docker sauber integrieren

Hot-Path-Analyse

Langsame Observer, Plugins und Templates identifizieren und beheben

Produktions-Sampling

Sicheres, kontinuierliches Profiling ohne spürbaren Overhead

10. Zusammenfassung

Magento-Profiling mit Blackfire und Xhprof löst ein Kernproblem: Statt vermuteter Ursachen liefern Flame Graphs und Call Graphs messbare Fakten darüber, welche Observer, Plugins oder Templates tatsächlich Zeit kosten. Blackfire eignet sich für tiefe, gezielte Deep-Dive-Analysen mit vollständigem Call Graph, Xhprof beziehungsweise Tideways für dauerhaftes, ressourcenschonendes Sampling, das auch in Produktion mitläuft, ohne den Shop spürbar zu verlangsamen. Der eingebaute Magento Profiler bleibt das schnellste Werkzeug für einen ersten lokalen Check ohne zusätzliche Extension.

Der entscheidende Hebel liegt selten in einer einzelnen spektakulären Optimierung, sondern in der konsequenten Praxis: vor jeder Optimierung profilieren, nach jeder Optimierung erneut profilieren und die beiden Profile direkt vergleichen. Wer diese Routine etabliert und produktives Sampling mit niedriger Rate dauerhaft aktiviert, erkennt Performance-Regressionen, bevor sie zu einem echten Problem für Nutzer und Umsatz werden.

Magento-Profiling - Das Wichtigste auf einen Blick

Blackfire für Deep Dives

Vollständiger Call Graph mit I/O- und SQL-Zeiten, ideal für gezieltes Debugging einzelner Requests.

Xhprof/Tideways für Monitoring

Sehr geringer Overhead, produktionstaugliches Sampling über tideways.sample_rate.

Magento Profiler für Schnellchecks

MAGE_PROFILER=html ohne zusätzliche Extension, ideal für lokale Ad-hoc-Analysen.

Immer vergleichen

Vorher/Nachher-Profile unter identischen Bedingungen gegenüberstellen, nicht nur Gesamtzeit, sondern auch Aufrufanzahl prüfen.

11. FAQ: Magento-Profiling mit Blackfire und Xhprof

1Warum reicht gefühlte Langsamkeit nicht als Diagnose?
Die tatsächlich teuersten Codepfade liegen selten dort, wo man sie intuitiv vermutet. Ohne Messung mit einem Profiler bleibt jede Optimierung ein Ratespiel.
2Was ist der Unterschied zwischen Blackfire und Xhprof/Tideways?
Blackfire ist ein SaaS-Tool mit vollständigem Call Graph und Web-Oberfläche. Xhprof/Tideways ist eine leichtgewichtige Extension mit sehr geringem Overhead, ideal für dauerhaftes Sampling.
3Wie installiere ich die Blackfire Probe im Docker-Setup?
Als Extension im PHP-FPM-Container installieren, mit Server- und Client-Credentials aus dem Dashboard konfigurieren, dann per blackfire curl oder blackfire run profilieren.
4Wie aktiviere ich Xhprof oder Tideways in PHP?
Über eine ini-Datei mit extension=tideways_xhprof.so. tideways.sample_rate steuert automatisches Sampling versus manuelles Profiling per xhprof_enable()/xhprof_disable().
5Wie nutze ich den eingebauten Magento Profiler?
Über MAGE_PROFILER=html vor dem bin/magento-Aufruf. Ergebnis ist eine profiler.html mit aufklappbarem Baum aller gemessenen Timer.
6Wie lese ich einen Flame Graph richtig?
x-Achse zeigt relative Breite der verbrachten Zeit, y-Achse die Aufruftiefe. Breite, flache Balken weit oben sind die lohnendsten Optimierungsziele.
7Woran erkenne ich einen Hot Path in einem Call Graph?
An hoher exklusiver Zeit und auffällig vielen Wiederholungen desselben Aufrufs, typischerweise bei Observern und Plugins unterhalb von dispatch oder Interceptor.
8Wie vergleiche ich zwei Profile vorher/nachher?
Unter identischen Bedingungen mit mehreren Wiederholungen. Blackfire bietet eine eingebaute Vergleichsfunktion, für Xhprof/Tideways ein Diff-Tool. Auch die Aufrufanzahl vergleichen, nicht nur die Gesamtzeit.
9Ist Profiling in Produktion sicher?
Ja, mit Sampling statt Vollprofilierung. Xhprof/Tideways erlaubt native Sampling-Raten mit sehr geringem Overhead, Blackfire per Trigger-Header für einzelne Requests.
10Welches Overhead-Budget ist für Produktions-Sampling akzeptabel?
Typischerweise unter zwei Prozent bei niedriger Sampling-Rate. Health-Check-Endpunkte und statische Assets sollten grundsätzlich ausgeschlossen werden.