Die PHP-Leistung verbessert sich ständig. Wenn Sie es jedoch unsachgemäß verwenden oder nicht vorsichtig sind, können Sie dennoch in die Fallstricke der internen Implementierung von PHP geraten. Ich bin vor ein paar Tagen auf ein Leistungsproblem gestoßen
Die Leistung von PHP hat sich verbessert. Wenn Sie es jedoch unsachgemäß verwenden oder nicht vorsichtig sind, können Sie dennoch in die Fallstricke der internen Implementierung von PHP geraten. Ich bin vor ein paar Tagen auf ein Leistungsproblem gestoßen.
Folgendes ist passiert: Eine unserer Schnittstellen brauchte jedes Mal 5 Sekunden, um zurückzukehren. Wir überprüften den Code gemeinsam und stellten „überrascht“ fest, dass er in einer Schleife aufgerufen wurde (ca. 900). Mal). Obwohl es sich verdoppelt hat, ist das natürlich kein Ergebnis, das wir akzeptieren können!
Die Menge an Code, die das Leistungsproblem verursachte, war nicht groß. Nachdem wir das E/A-Problem behoben hatten, schrieben wir einen Testcode und tatsächlich trat das Problem schnell wieder auf.
Code kopieren Der Code lautet wie folgt:
<?php $y="1800"; $x = array(); for($j=0;$j<2000;$j++){ $x[]= "{$j}"; } for($i=0;$i<3000;$i++){ if(in_array($y,$x)){ continue; } } ?>
shell$ time /usr/local/php/bin/ php test. php
real 0m1.132s
user 0m1.118s
sys 0m0.015s
Ja, wir verwenden Zahlen vom Typ String der Cache. Verdammt! Hier wird es also speziell in eine Zeichenfolge konvertiert (wenn es sich direkt um eine Zahl handelt, tritt dieses Problem nicht auf, Sie können es selbst überprüfen). Es ist ersichtlich, dass die verbrauchte Zeit 1 Sekunde beträgt, also nur 3000 Zyklen. Die nachfolgende Systemzeit ist auch dazu bestimmt, dass wir mit Strace keine effektiven Informationen erhalten.
shell$ strace -ttt -o xxx /usr/local/php/bin/php test.php
shell$ less xxx
us Ich habe nur gesehen, dass die Verzögerung zwischen diesen beiden Systemaufrufen sehr groß war, aber ich wusste nicht, was getan wurde? Glücklicherweise enthalten die Debugging-Tools unter Linux neben strace auch ltrace (natürlich gibt es auch dtrace und ptrace, die den Rahmen dieses Artikels sprengen und daher weggelassen werden).
Zitat: strace wird verwendet, um die Systemaufrufe oder Signalgenerierung eines Prozesses zu verfolgen, während ltrace verwendet wird, um den Prozess des Aufrufs von Bibliotheksfunktionen zu verfolgen (über IBM Developerworks).
Um Störfaktoren zu eliminieren, weisen wir $x direkt der Array-Form („0“, „1“, „2“, …) zu, um zu vermeiden, dass übermäßige Malloc-Aufrufe die Ergebnisse beeinflussen. Führen Sie
shell$ ltrace -c /usr/local/php/bin/php test.php aus
Wie in Abbildung 2 gezeigt
Wir haben gesehen, dass die Bibliotheksfunktion __strtol_internal sehr häufig aufgerufen wird, was zu übertrieben ist. Dann habe ich überprüft, wozu diese Bibliotheksfunktion __strtol_internal dient. Einfach ausgedrückt Konvertieren Sie die Zeichenfolge in eine lange Ganzzahl. Es kann davon ausgegangen werden, dass die PHP-Engine erkannt hat, dass es sich um eine Zeichenfolge handelt. Daher wird erwartet, dass sie zum Vergleich in eine lange Ganzzahl konvertiert wird. Dieser Konvertierungsprozess nimmt daher zu viel Zeit in Anspruch es noch einmal:
Code kopieren Der Code lautet wie folgt:
shell$ ltrace -e "__strtol_internal" /usr/local /php/bin/php test.php
kann problemlos eine große Anzahl von Aufrufen wie im Bild unten abfangen Bei einem losen Vergleich werden zuerst zwei numerische Zeichenfolgen konvertiert. Vergleichen Sie den Typ „Long Integer“ erneut, aber ich weiß nicht, dass dies die Leistung beeinträchtigt.
Da wir nun den Kern des Problems kennen, haben wir viele Lösungen. Die einfachste besteht darin, den dritten Parameter zu in_array auf true hinzuzufügen, was zu einem strengen Vergleich wird. Während auch zum Vergleichen von Typen die cleveren Konvertierungstypen von PHP vermieden werden und der Code wie folgt lautet:
Kopieren Sie den Code Der Der Code lautet wie folgt:
<?php $y="1800"; $x = array(); for($j=0;$j<2000;$j++){ $x[]= "{$j}"; } for($i=0;$i<3000;$i++){ if(in_array($y,$x,true)){ continue; } } ?>
Code kopieren Der Code lautet wie folgt:
shell$ time /usr/local/php/bin/php test.php
real 0m0.267s
Benutzer 0m0.247s
sys 0m0.020s
Um ein Vielfaches schneller! ! ! Man erkennt, dass sich die von sys benötigte Zeit kaum verändert hat. Wenn wir erneut verfolgen, müssen wir $x immer noch direkt zuweisen, um die Interferenz von Malloc-Aufrufen zu beseitigen. Da wir es in unserer eigentlichen Anwendung sofort aus dem Cache abrufen, gibt es im Beispielcode keine solche Schleife, die angewendet werden muss Erinnerung.
Erneut ausführen
Kopieren Sie den Code Der Code lautet wie folgt:
shell$ ltrace -c /usr/local /php/bin /php test.php
Wie unten gezeigt:
__ctype_tolower_loc nimmt die meiste Zeit in Anspruch! Ich habe überprüft, was die Bibliotheksfunktion __ctype_tolower_loc macht: Das einfache Verständnis besteht darin, Zeichenfolgen in Kleinbuchstaben umzuwandeln. Bedeutet das also, dass in_array-Vergleichszeichenfolgen nicht zwischen Groß- und Kleinschreibung unterscheiden? Tatsächlich hat dieser Funktionsaufruf wenig mit unserem in_array zu tun. Es ist besser, einen Blick auf den Quellcode von PHP zu werfen. Okay, ich kann nicht weitermachen. Gerne können Sie mit mir kommunizieren. Bitte korrigieren Sie mich, wenn ich etwas Falsches schreibe.
——————29.08.2013 Trennlinie————————
Ich habe am Abend den folgenden Quellcode von PHP 5.4.10 gelesen und bin interessiert in in_array Es ist so groß, haha. Es befindet sich in Zeile 1248 von ./ext/standard/array.c. Sie können sehen, dass die Funktion array_serach dies auch anpasst, aber der letzte Parameter ist anders! Nach einigem Nachverfolgen rief er im Falle eines losen Vergleichs in_array schließlich die Funktion zendi_smart_strcmp (eigentlich eine „intelligente“ Funktion) zum Vergleich auf, die sich in ./Zend/zend_operators.c befindet. Wir haben ltrace verwendet, um eine große Anzahl erfasster Daten zu konvertieren in ganze Zahlen umwandeln. Die Operation ist das Verhalten von is_numeric_string_ex.
Die Funktion is_numeric_string_ex ist in ./Zend/zend_operators.h definiert. Nach einer Reihe von Beurteilungen und Konvertierungen wird strtol in Zeile 232 aufgerufen Die im Artikel erwähnte Konvertierung einer Zeichenfolge in eine lange Ganzzahl mit Bildern und Fakten
Verwandte Empfehlungen:
Wieder einmal bin ich auf verstümmelte Zeichen gestoßen
als PHP Chinesisch in MYSQL einfügte und anzeigte.
Das obige ist der detaillierte Inhalt vonEs treten Probleme mit geringer Leistung bei PHPs in_array auf. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!