
Hallo Habr! Mein Name ist Timur Shagiakhmetov, ich bin ein PHP-Entwickler bei
Badoo .
Die Anwendungsleistung ist eines der wichtigsten Kriterien für die Qualität der Arbeit eines Programmierers. Bei der Optimierung von PHP-Anwendungen ist der Assistent der Profiler.
Kürzlich haben wir
darüber gesprochen, welche Tools wir für die Profilerstellung verwenden. Ich möchte Sie daran erinnern: Eines der Tools für die Leistungsanalyse, bei dem nicht klar ist, welche Teile des Codes die
Verlängerung der Antwortgenerierungszeit beeinflusst haben, ist
XHProf . Dies ist eine Erweiterung für PHP, mit der Sie Code auf einem Kampfserver profilieren und anschließend verbessern können.
Ich hätte aber auch gerne eine Vorgeschichte von Produktivitätsänderungen, damit Sie nachverfolgen können, was und wann sich die Verschlechterung ausgewirkt hat, oder? Zu diesem
Zweck haben wir vor etwa einem Jahr
Liveprof entwickelt, ein Tool zum automatischen Profiling aller Anforderungen mit einer Schnittstelle zur Analyse von Änderungen der Anwendungsleistung.
Mit unserem Tool können Sie die Leistungsänderung eines Teils des Codes analysieren und die Stellen finden, an denen er am meisten gefallen ist. Gleichzeitig muss es nicht speziell aktiviert werden und darauf warten, dass sich Statistiken ansammeln. Es ist immer aktiv und sammelt Daten für einen bestimmten Bruchteil aller Anforderungen.
In diesem Artikel werde ich über Implementierungsdetails und Funktionen der Verwendung dieses Tools sprechen.
Ein bisschen über XHProf
Zunächst einige Worte zu den Funktionen von XHProf. Dies ist ein Profiler für PHP, der als Erweiterung in C geschrieben wurde. Es wurde auf Facebook entwickelt und gemeinfrei veröffentlicht. Es verfügt über mehrere Gabeln (
Uprofiler ,
Tideways ), die auf der Ebene des Ausgabedatenformats vollständig kompatibel sind.
XHProf setzt Timer für alle Funktions- / Methodenaufrufe. Die Verwendung ist mit einem gewissen Aufwand verbunden. Aber sie sind nicht so groß und erlauben es, sie in der Produktion zu verwenden.
Das Ergebnis von XHProf ist ein Array von Elementen im folgenden Format:
$data = [ 'parentMethodName==>childMethodName' => [ 'ct' => 1 'wt' => 8 'cpu' => 11 'mu' => 528 'pmu' => 0 ] ];
wo
parentMethodName
und
childMethodName
sind die übergeordneten bzw.
childMethodName
Methoden.
ct
- die Anzahl der Anrufe im Kontext der Anfrage;
wt
- Ausführungszeit der Anforderung (besteht aus der vom Prozessor aufgewendeten Zeit und der Wartezeit auf E / A oder die Antwort eines anderen Dienstes);
cpu
- Zeit, die der Prozessor für die Verarbeitung der Anforderung aufgewendet hat;
mu
- Änderung des Speicherverbrauchs nach einem Methodenaufruf;
pmu
- Änderung des
pmu
Speicherverbrauchs nach einem Methodenaufruf.
Einige andere Optionen sind ebenfalls möglich.
XHProf enthält auch Tools zur Visualisierung der so erzielten Ergebnisse. Für jede Profilierungsoperation erhalten wir eine Tabelle mit einer Reihe von Parametern für jede Methode.
Zum Beispiel
Blasensortierungsergebnis <?php class ArrayGenerator { public function getRandomArray(int $count): array { $array = []; for ($i = 0; $i < $count; $i++) { $array[] = rand(0, 1000); } return $array; } } class BubbleSorter { public function sort(&$array): void { $len = count($array); for ($i = 0; $i < $len ; $i++) { for ($j = 0; $j < $len - $i - 1; $j++) { if ($array[$j] > $array[$j + 1]) { $this->swap($array[$j], $array[$j + 1]); } } } } private function swap(&$a, &$b): void { $tmp = $a; $a = $b; $b = $tmp; } public function isSorted(array $array): bool { $len = count($array); for ($i = 0; $i < $len - 1; $i++) { if ($array[$i] > $array[$i + 1]) { return false; } } return true; } } class ArrayPrinter { public function print(array $array, string $delimiter = ' '): void { echo implode($delimiter, $array) . PHP_EOL; } } xhprof_enable(); $n = 10; $arrayGenerator = new \ArrayGenerator(); $array = $arrayGenerator->getRandomArray($n); $sorter = new BubbleSorter(); if (!$sorter->isSorted($array)) { $sorter->sort($array); } $printer = new \ArrayPrinter(); $printer->print($array); $xhprof_data = xhprof_disable();

Sie können in jede Methode gehen, um herauszufinden, welche Methoden wie viele Ressourcen verbraucht haben.
Sie können sich auch das Anrufdiagramm ansehen und die ressourcenintensivsten Methoden hervorheben:

XHProf ist nützlich, um die Leistung jeder Anforderung manuell zu analysieren. Es ist uns aber auch wichtig, das große Ganze zu sehen. Sie müssen verstehen, wie sich die Leistung im Laufe der Zeit verändert hat. Zu diesem Zweck wurde ein Tool entwickelt, mit dem Abfragen im automatischen Modus profiliert und in der Weboberfläche analysiert werden können.
Liveprof: Ergebnisse aggregieren und Verlauf behalten
Wie erhalte ich einen Profilverlauf?
Zuerst müssen Sie den automatischen Start des Profilers konfigurieren und die Ergebnisse speichern. Die Leistung ist nicht konstant und schwankt von Start zu Start. Um den Einfluss solcher Schwankungen zu vermeiden, verwenden wir die gemittelten Daten mehrerer Abfragen. Als Ergebnis erhalten wir aggregierte Ergebnisse für jede Abfrage, z. B. Minimum, Maximum, Durchschnitt und 95. Perzentil. Dies hilft, schwierige Dinge zu finden, die möglicherweise nicht bei jeder Anfrage aufgerufen werden.
Unser Tool hat sowohl Vorteile als auch einige Einschränkungen.
Was der Aggregator tun kann:
- Automatische Profilerstellung für jede N-te Anforderung.
- Tägliche Zusammenfassung der gesammelten Profile.
- Die Möglichkeit, Diagramme der Änderungen in jedem vom Profiler gemessenen Parameter anzuzeigen. Zum Beispiel wt, cpu, mu, pmu, wie oben beschrieben.
- Zeigen Sie die Leistungsänderung einer Methode für ein bestimmtes Intervall an.
- Flammendiagramm basierend auf den neuesten aggregierten Daten.
- Suchen Sie nach Abfragen, die eine bestimmte Methode aufrufen
Einschränkungen:
- Da es sich bei unserem Tool um ein aggregiertes Tool handelt, können Sie die Leistung einer Abfrage (z. B. der langsamsten) nicht ermitteln. Die Ergebnisse werden über den letzten Tag gemittelt. Dies reicht jedoch aus, um die allgemeine Leistungsdynamik zu bewerten. Wenn eine Anforderung in der Ausführungsgeschwindigkeit abrutscht, ändern sich der Durchschnittswert, das 95. Perzentil und die maximale Ausführungszeit.
- Sie können den vollständigen Aufrufstapel nicht eindeutig wiederherstellen, da XHProf nur eindeutige Eltern-Kind-Paare mit der Summe der Werte der verbrauchten Ressourcen zurückgibt.
- Laufzeitfehler im Zusammenhang mit XHProf-Overhead anfordern. Der Unterschied ist nicht so groß, muss aber bei der Messung der Ausführungszeit der Abfrage berücksichtigt werden.
So verwenden Sie den Profiler
- Zunächst muss der Profiler mit der Site oder dem Skript verbunden werden. Die bequemste Möglichkeit, das Tool zu verwenden , besteht darin, den Profiler automatisch zu starten :
php composer.phar require badoo/liveprof # Run a script to configure database LIVE_PROFILER_CONNECTION_URL=mysql://db_user:db_password@db_mysql:3306/Profiler?charset=utf8 php vendor/badoo/liveprof/bin/install.php
Es unterstützt Versionen von PHP ab 5.4 und ist mit minimalem Overhead behaftet, sodass Sie es in einer Kampfumgebung verwenden können. Das Tool erkennt automatisch die verwendete Profiler-Erweiterung: XHProf , Uprofiler oder Tideways . Beim Start müssen Sie Parameter für die Verbindung zur Datenbank und die Profileinstellungen angeben.
Beispiel für die Verwendung in Code mit Standardeinstellungen:
<?php include 'vendor/autoload.php'; \Badoo\LiveProfiler\LiveProfiler::getInstance()->start();
Profilerstellungsergebnisse werden in der Datenbank gespeichert. Einmal am Tag findet ein Aggregationsprozess statt. Wählen Sie dazu alle Datensätze für eine bestimmte Anforderung pro Tag aus und berechnen Sie die aggregierten Funktionen für jeden der Parameter. Aggregationsfunktionen können erweitert oder neu definiert werden.
Folgendes ist jetzt verfügbar:
- mindestens pro Tag;
- Maximum pro Tag;
- Tagesdurchschnitt
- 95. Perzentil des Tages.
- Der Aggregator -Webclient wird verwendet, um die Aggregation zu konfigurieren und die Ergebnisse anzuzeigen. Der einfachste Weg, es in einem Docker-Container zu installieren:
git clone https:
- Vor dem ersten Start müssen Sie die Datenbankverbindungsparameter, eine Liste der Felder und die verwendeten Aggregatfunktionen in der Konfigurationsdatei src / config / services.yaml konfigurieren. Führen Sie dann das Installationsskript aus:
docker-compose exec web bash install.sh
- Es ist notwendig, automatisch ausgeführte Skripte zur Aggregation und Bereinigung alter Daten in Kronen zu registrieren:
- Um mit Testdaten zu füllen, können Sie das Skript ausführen:
docker-compose exec web php /app/bin/cli.php example:a-week-degradation
Schnittstellenbeschreibung
Das Webinterface ist verfügbar unter: 127.0.0.1:8000.
Standardmäßig wird eine Seite mit einer Liste aggregierter Abfragen geöffnet. Es macht es einfach, eine interessierende Abfrage zu finden, alle Abfragen nach einem der Parameter zu sortieren und eine bestimmte Abfrage neu zu aggregieren, um die neuesten Ergebnisse anzuzeigen:

Bei der Arbeit mit dem Tool wird am häufigsten eine Seite mit einer Liste von Methoden und Diagrammen mit Leistungsänderungen verwendet. Sie können den Aufrufstapel durchgehen, den Verbrauch der einzelnen Parameter sowie Diagramme der Leistungsänderungen für ein bestimmtes Intervall beobachten:
Auf einer Seite mit einer vollständigen Liste der aufgerufenen Methoden können Sie die gewünschte Methode schnell finden und die Diagramme anzeigen, indem Sie zur Diagrammseite gehen:
Auf der Seite mit dem Flammengraphen der letzten aggregierten Abfrage können Sie die schwersten Teile visuell identifizieren.Die Verwendung von XHProf schränkt die Genauigkeit des Ergebnisses ein. Dies liegt daran, dass der Profiler keinen vollständigen Aufrufbaum zurückgibt, sondern nur die Eltern-Kind-Paare. Wenn außerdem ein Methodenpaar von verschiedenen Stellen der Anwendung aufgerufen wurde, erhalten wir als Ergebnis die aufgewendete Zeit. Für ein Flammendiagramm benötigen Sie einen vollständigen Aufrufbaum. Bei der Wiederherstellung eines solchen Baums werden die Parameterwerte unter Berücksichtigung der von den Eltern aufgewendeten Zeit normalisiert.
Eine Seite mit einer Liste von Methoden, die während des ausgewählten Intervalls langsamer geworden sind.Außerdem können Sie für jede Methode sehen, welcher der untergeordneten Aufrufe die Leistung am meisten beeinflusst hat. Im folgenden Screenshot sehen Sie beispielsweise, dass die
ServiceApi::getAvailableServices()
-Methode 116 ms langsamer ausgeführt wurde. Der Grund dafür war das Hinzufügen eines Aufrufs von
ServiceApi::getGifts()
(Änderung um 56 ms) und eine Erhöhung der Anzahl der Aufrufe der
ServiceApi::getConfigForList()
-Methode von 1 auf 5 (weitere 50 ms):

Wenn im Voraus nicht bekannt ist, bei welcher Abfrage sich die Leistung am deutlichsten geändert hat, hilft eine Seite mit einer Liste von Methoden, die ohne Verweis auf eine bestimmte Abfrage langsamer geworden sind:
Eine Seite, die nach Abfragen sucht, die eine bestimmte Methode aufrufen.Sie können die Ausführungszeit in verschiedenen Anforderungen vergleichen. Auch nützlich, um nicht verwendeten Code zu finden:

Anpassungsfunktionen
Das Tool bietet zahlreiche Anpassungsmöglichkeiten:
Fazit
Ich hoffe, unser Tool wird anderen Entwicklern nützlich sein. Auf diese Weise können Sie die Leistungsänderung eines Teils des Codes ohne Verwendung zusätzlicher Timer überprüfen. Dies erleichtert auch den Optimierungsprozess, da Sie jetzt sehen können, welche Auswirkungen die Verschlechterung der Anwendungsleistung im Laufe der Zeit hatte.
Es ist auf GitHub verfügbar:
github.com/badoo/liveprof , die Weboberfläche lautet
github.com/badoo/liveprof-ui .
Das Tool befindet sich in der aktiven Entwicklung und kann einige Fehler enthalten. Hoffentlich wird es mit der Beteiligung der Community noch besser. Die Pläne sehen vor, neben XHProf auch andere Profiler zu unterstützen und die Liste der unterstützten Datenbanken zu erweitern.
Senden Sie uns Feedback und Fragen zur Verwendung in
Telegrammen , Fehlern und Pull-Anfragen - direkt an
GitHub . Wir freuen uns über Kommentare und Vorschläge!
Besonderer Dank geht an
Gregory für die Idee und die erste Umsetzung.