Leistungsoptimierung von PHP-Anwendungen
Der größte Vorteil der Programmierung in PHP besteht darin, wie einfach es ist, diese Programmiersprache und ihre umfangreichen Bibliotheken zu erlernen. Selbst wenn wir nicht viel über die Funktionen wissen, die wir verwenden müssen, können wir erraten, wie wir eine bestimmte Aufgabe erledigen können.
Obwohl PHP sehr einfach und leicht zu erlernen ist, müssen wir noch ein wenig Zeit damit verbringen, einige PHP-Programmierkenntnisse zu erlernen, insbesondere solche, die sich auf Leistung und Speichernutzung beziehen. In PHP gibt es viele Tricks, mit denen wir die Speichernutzung reduzieren und die Anwendungsleistung verbessern können. In diesem Artikel stellen wir kurz die Analyse von PHP-Anwendungen vor, wie man den Skriptcode ändert und verschiedene Parameterwerte vor und nach der Optimierung vergleicht.
Durch das Festlegen von Timing-Prozeduren im Programm und die wiederholte Ausführung dieser Codes können wir eine Reihe von Daten über die Ausführungsgeschwindigkeit des Programms erhalten. Diese Daten können verwendet werden, um Engpässe im Programm zu erkennen und es zu optimieren, um die Leistung des Programms zu verbessern Anwendung.
Vielleicht haben Leser von der PEAR-Bibliothek gehört. Wir werden die PEAR-Bibliothek verwenden, um Beispiele zu erstellen, die wir während der Analyse verwenden müssen. Dies ist auch die einfachste Möglichkeit, vorhandenen Code zu analysieren. Es ermöglicht uns, den Code zu analysieren, ohne kommerzielle Produkte zu verwenden.
Der Name der Bibliothek, die wir verwenden werden, ist PEAR::Benchmark und sie ist sehr nützlich für die Profilerstellung und Leistungstests des Codes. Diese Bibliothek stellt eine Klasse namens Benchmark_Timer() bereit, die die Zeit zwischen einem Funktionsaufruf und dem nächsten Funktionsaufruf aufzeichnen kann. Wenn wir die Leistung des Codes testen, können wir ein detailliertes Skriptausführungsergebnis erhalten, das sehr einfach ist, wie folgt:
include_once("Benchmark/Timer.php");
$bench = neuer Benchmark_Timer;
$bench->start();
$bench->setMarker('Start des Skripts');
// Jetzt für ein paar Minuten im Schlafzustand
Schlaf(5);
$bench->stop();
// Analyseinformationen vom Timer abrufen
print_r($bench->getProfiling());
?>
Die Ausgabe nach der Ausführung des obigen Codes lautet wie folgt:
Array
(
[0] => Array
(
[Name] => Start
[Zeit] => 1013214253.05751200
[diff] => -
[Gesamt] => 0
)
[1] => Array
(
[Name] => Start des Skripts
[Zeit] => 1013214253.05761100
[diff] => 9.8943710327148E-05
[Gesamt] => 9.8943710327148E-05
)
[2] => Array
(
[Name] => Stopp
[Zeit] => 1013214258.04920700
[diff] => 4.9915959835052
[Gesamt] => 4,9916949272156
)
)
Die oben genannten Zahlen mögen wie eine unzusammenhängende Menge von Zahlen erscheinen, aber wenn das Programm größer ist, können diese Zahlen sehr nützlich sein.
Vielleicht kann die Mehrheit der Leser auch vermuten, dass der erste Eintrag im Array beispielsweise die eigentliche Methode zum Aufrufen der Klasse Benchmark_Timer() ist
$bench->start(), $bench->setMarker() und $bench->stop() Die mit diesen Einträgen verknüpften Zahlen sind nun recht einfach:
[0] => Array
(
[Name] => Start
[Zeit] => 1013214253.05751200
[diff] => -
[Gesamt] => 0
)
Der Zeiteintrag bezieht sich auf den UNIX-Zeitstempel beim Aufruf der start()-Methode von Benchmark_Timer(). Der Diff-Eintrag gibt das Zeitintervall zwischen diesem Aufruf und dem letzten Aufruf an, ein Dash, der Gesamteintrag bezieht sich auf die Gesamtzeit, die der Code vom Start des Tests bis zu diesem bestimmten Aufruf ausgeführt wurde. Werfen wir einen Blick auf die Ausgabe des nächsten Arrays:
[1] => Array
(
[Name] => Start des Skripts
[Zeit] => 1013214253.05761100
[diff] => 9.8943710327148E-05
[Gesamt] => 9.8943710327148E-05
)
Anhand der obigen Zahlen können wir erkennen, dass das Programm nach dem Aufruf von $bench->start() 9,8943710327148E-05 Sekunden (also 0,0000989 Sekunden) läuft, bevor es $bench->setMarker(…) aufruft.
Ein echtes Leistungstest-Erlebnis
Das obige Beispiel ist zwar gut, aber wirklich kein gutes Beispiel für die Entscheidung, wie Sie das Code-Design Ihrer Website optimieren können. Im Folgenden werde ich meine persönlichen Erfahrungen als Website-Techniker nutzen, um zu veranschaulichen, wie sich Leistungsprobleme lösen lassen.
Ich verstehe den von der Website verwendeten Code nicht wirklich, da er über viele Jahre hinweg basierend auf spezifischen Anforderungen entwickelt wurde – ein Modul enthält den Website-Konvertierungscode, ein anderes Modul zeichnet die Nutzung der Website auf und die anderen Module haben ihre eigenen Rolle eines jeden. Der Hauptentwickler der Website und ich erkannten beide, dass der Code der Website optimiert werden musste, aber wir wussten nicht, wo das Problem lag.
Um die Aufgabe so schnell wie möglich abzuschließen, begann ich, den Hauptskriptcode der Website zu studieren, fügte einige $bench->setMarker()-Befehle zu allen Skriptcodes und den darin enthaltenen Dateien hinzu und analysierte dann die Ausgabe von $bench ->getProfiling(), und ich war von den Ergebnissen überrascht. Es stellte sich heraus, dass das Problem in einem Funktionsaufruf im Zusammenhang mit dem Konvertierungscode lag, um einen bestimmten Sprachnamen (z. B. en für Englisch) zu erhalten, der hunderte Male verwendet wurde auf jeder Seite. Bei jedem Aufruf dieser Funktion fragt der Skriptcode eine MySQL-Datenbank ab, um den tatsächlichen Sprachnamen aus einer Datenbanktabelle abzurufen.
Deshalb schaffen wir ein Puffersystem für diese Art von Informationen. Nach nur zwei Arbeitstagen haben wir die Leistung des Systems erheblich verbessert und die Anzahl der Seitenaufrufe stieg in der ersten Woche um 40 %. Dies ist natürlich nur ein Beispiel dafür, wie die Analyse von Code die Leistung einer Internetanwendung oder Internet-Website verbessern kann.
Aufruf einer Leistungstestfunktion
Obwohl Benchmark_Timer() besonders nützlich ist, wenn ein Skript oder eine Webseite (und die darin enthaltenen Dateien) analysiert wird, ist es nicht wissenschaftlich, da wir das Skript mehrmals laden müssen, um die analysierten Daten zu erhalten, und es ist nicht spezifisch für eine bestimmte Klasse oder Funktion . angerufen.
Eine andere Klasse in der PEAR::Benchmark-Bibliothek namens Benchmark_Iterator kann dieses Problem sehr gut lösen. Sie kann Analyseinformationen für eine bestimmte Funktion oder Klassenmethode anzeigen. Sein Zweck besteht darin, in der Lage zu sein, konsistente Ergebnisse aus Tests zu erhalten, denn wir wissen, dass wenn wir ein Skript einmal ausführen und die Ausführung 10 Sekunden dauert, das nicht bedeutet, dass die Ausführung jedes Mal 10 Sekunden dauert.
Sehen wir uns auf jeden Fall einige Beispiele an:
// Code zum Herstellen einer Verbindung zur Datenbank
include_once("DB.php");
$dsn = array(
'phptype' => 'mysql',
'hostspec' => 'localhost',
'database' => 'database_name',
'Benutzername' => 'Benutzername',
'password' => 'password'
);
$dbh = DB::connect($dsn);
Funktion getCreatedDate($id)
{
global $dbh;
> $stmt = „SELECT erstelltes_Datum FROM Benutzer WHERE id=$id“;
// Hier PEAR::DB verwenden
$created_date = $dbh-> getOne($stmt);
if ((PEAR::isError($created_date)) ||
(empty($created_date))) {
return false;
} anders {
return $created_date;
}
}
include_once 'Benchmark/Iterate.php';
$bench = new Benchmark_Iterate;
//Führen Sie die getDate-Funktion 10 Mal aus
$bench-> run(10, 'getCreatedDate', 1);
//Analyseinformationen drucken
print_r($bench->get());
?>
Das Ausführen des obigen Codes führt zu Ergebnissen ähnlich den folgenden:
Array
(
[1] => 0,055413007736206
[2] => 0,0012860298156738
[3] => 0,0010279417037964
[4] => 0,00093603134155273
[5] => 0,00094103813171387
[6] => 0,00092899799346924
[7] => 0,0010659694671631
[8] => 0,00096404552459717
[9] => 0,0010690689086914
[10] => 0,00093603134155273
[Mittelwert] => 0,0064568161964417
[Iterationen] => 10
)
Die obigen Zahlen sind leicht zu verstehen. Der mittlere Eintrag stellt die durchschnittliche Zeit von 10 Durchläufen der Funktion getCreatedDate() dar. Bei tatsächlichen Tests sollten Sie es mindestens 1000 Mal ausführen, aber die Ergebnisse dieses Beispiels reichen aus, um das Problem zu veranschaulichen.