Ist in PHP (>= 5.0) die Referenzübergabe schneller?
Lesezeit: 8 Minuten
Hanno Fietz
In PHP können Funktionsparameter per Referenz übergeben werden, indem dem Parameter in der Funktionsdeklaration ein kaufmännisches Und vorangestellt wird, wie folgt:
function foo(&$bar)
{
// ...
}
Jetzt ist mir bewusst, dass dies der Fall ist nicht entwickelt, um die Leistung zu verbessern, aber Funktionen zu ermöglichen, Variablen zu ändern, die normalerweise außerhalb ihres Gültigkeitsbereichs liegen.
Stattdessen scheint PHP Copy On Write zu verwenden, um zu vermeiden, dass Objekte (und möglicherweise auch Arrays) kopiert werden, bis sie geändert werden. Bei Funktionen, die ihre Parameter nicht ändern, sollte der Effekt also derselbe sein, als hätten Sie sie per Referenz übergeben.
Ich habe mich jedoch gefragt, ob die Copy On Write-Logik möglicherweise bei Pass-by-Reference kurzgeschlossen ist und ob dies Auswirkungen auf die Leistung hat.
ETA: Sicherlich gehe ich davon aus, dass es nicht schneller geht, und ich bin mir bewusst, dass Referenzen dafür nicht da sind. Also denke ich, dass meine eigenen Vermutungen ziemlich gut sind, ich suche nur nach einer Antwort von jemandem, der wirklich weiß, was definitiv unter der Haube passiert. In fünf Jahren PHP-Entwicklung fand ich es immer schwierig, qualitativ hochwertige Informationen über PHP-Interna zu bekommen, ohne die Quelle gelesen zu haben.
Siehe meine Frage für ein Beispiel, wo Referenzen die Dinge dramatisch verlangsamen können: stackoverflow.com/questions/3117604/…
– John Carter
30. Juni 2010 um 10:24 Uhr
ikary
In einem Test mit 100 000 Iterationen zum Aufrufen einer Funktion mit einer Zeichenfolge von 20 kB sind die Ergebnisse:
Funktion, die nur den Parameter liest / verwendet
pass by value: 0.12065005 seconds
pass by reference: 1.52171397 seconds
Funktion zum Schreiben / Ändern des Parameters
pass by value: 1.52223396 seconds
pass by reference: 1.52388787 seconds
Schlussfolgerungen
Übergeben Sie den Parameter als Wert ist immer schneller
Wenn die Funktion den Wert der übergebenen Variablen ändert, ist das praktisch dasselbe wie eine Referenzübergabe als eine Wertübergabe
Das sind großartige Informationen, aber ich bin neugierig: Welche Version von PHP haben Sie für diesen Test verwendet?
– Andrew Ensley
23. Februar 2012 um 16:46 Uhr
Das macht nicht wirklich viel Sinn. Das ist eine wirklich sehr, sehr ineffiziente Handhabung von Referenzen.
– Jonathan
11. März 2013 um 6:05 Uhr
Siehe Antwort unten. Es spricht über die Verwendung großer Arrays und mehr.
– Zeichnete LeSueur
17. Oktober 2013 um 13:47 Uhr
Berücksichtigt dieser Test die zusätzliche Zeit, die eine Pass-by-Value-Funktion zum Kopieren und Zurückgeben des geänderten Werts benötigt?
– Chris Middleton
11. September 2014 um 18:52 Uhr
Ich habe festgestellt, dass das Übergeben von Referenzen langsam ist, wenn Sie die erhalten count() des Arrays in der Funktion, die das Array als Referenz abruft.
– Zeichnete LeSueur
21. Dezember 2016 um 0:18 Uhr
Paul Dixon
Die Zend-Engine verwendet Copy-on-Write, und wenn Sie selbst eine Referenz verwenden, entsteht ein wenig zusätzlicher Overhead. Kann nur finden diese Erwähnung zum Zeitpunkt des Schreibens und Kommentare in das Handbuch weitere Links enthalten.
(EDIT) Die Handbuchseite auf Objekte und Referenzen enthält ein wenig mehr Informationen darüber, wie sich Objektvariablen von Referenzen unterscheiden.
Sie sagen also, dass es tatsächlich der Leistung schadet (auch wenn die Auswirkungen vielleicht sehr unbedeutend sind)? Das ist interessant, danke!
– Hanno Fietz
7. Oktober 2008 um 13:25 Uhr
Der (etwas akademische) Gesamtleistungsverlust sollte nur auftreten, wenn Sie niemals die ursprüngliche Datenstruktur manipulieren. Wenn Sie es vorhaben, sollten Sie es tatsächlich tun gewinnen Leistung, da Sie Copy-on-Write vermeiden.
– Tomalak
7. Oktober 2008 um 14:05 Uhr
Ja, zugegeben, das ist ein bisschen akademisch. Es ist nur so, dass ich sehr frustriert war, weil ich missverstanden hatte, wie PHP intern funktioniert, und das hat mich ein bisschen pedantisch gemacht, es herauszufinden. Mir scheint, dass gute Quellen zu PHP-Interna schwieriger zu finden sind als bei anderen Sprachen, zB Python
– Hanno Fietz
7. Oktober 2008 um 19:06 Uhr
Ich habe einige Tests dazu durchgeführt, weil ich mir der gegebenen Antworten nicht sicher war.
Meine Ergebnisse zeigen, dass das Übergeben großer Arrays oder Zeichenfolgen als Referenz wesentlich schneller ist.
Hier sind meine Ergebnisse:
Die Y-Achse (Runs) gibt an, wie oft eine Funktion in 1 Sekunde * 10 aufgerufen werden könnte
Der Test wurde für jede Funktion/Variable 8 mal wiederholt
Und hier sind die Variablen, die ich verwendet habe:
function pass_by_ref(&$var) {
}
function pass_by_val($var) {
}
Dieser Test spiegelt jedoch keinen realen Anwendungsfall wider. Leute übergeben oft per Referenz, wenn sie nicht mehrere Werte zurückgeben können, z. B. die Übergabe einer Referenz an ein Fehler-Array. Ein besserer Test wäre so etwas: function pass_by_ref($val, &$errors) { if($val < 0) { $errors []= "val < 0"; return false; } else return true; } … und … function pass_by_val($val, $errors) { if($val < 0) { $errors []= "val < 0"; return array("errors" => $errors, "result" => false); } else return array("errors" => $errors, "result" => true);}.
– Chris Middleton
11. September 2014 um 18:57 Uhr
wäre schön gewesen, auch Variationen zu haben, bei denen innerhalb des Arrays geändert wird und entweder die Änderungen zurückgegeben und erneut übernommen, durch Referenz zurückgegeben und erneut übernommen oder nicht zurückgegeben, sondern aufgrund des referenzierten Parameters erneut übernommen werden. nur sagen.
– hakre
25. Dezember 2014 um 12:30 Uhr
Keine der Funktionen ändert die Daten im Array.
– David Spector
24. Februar 2021 um 13:38 Uhr
Ich habe mit Werten und Referenzen von 10k-Byte-Strings experimentiert, die an zwei identische Funktionen übergeben wurden. Man nimmt das Argument als Wert und das zweite als Referenz. Sie waren allgemeine Funktionen – nehmen Sie ein Argument, führen Sie eine einfache Verarbeitung durch und geben Sie einen Wert zurück. Ich habe 100.000 Aufrufe von beiden durchgeführt und herausgefunden, dass Referenzen nicht darauf ausgelegt sind, die Leistung zu steigern – der Referenzgewinn lag bei 4-5 % und wächst nur, wenn die Zeichenfolge groß genug wird (100.000 und länger, das führte zu einer Verbesserung von 6-7 %). . Also, mein Fazit ist Verwenden Sie keine Referenzen, um die Leistung zu steigern, dafür ist dieses Zeug nicht da.
Ich habe PHP Version 5.3.1 verwendet
Ich bin mir ziemlich sicher, dass nein, es ist nicht schneller. Darüber hinaus heißt es im Handbuch ausdrücklich, nicht zu versuchen, Referenzen zur Leistungssteigerung zu verwenden.
Edit: Ich kann nicht finden, wo das steht, aber es ist da!
Ich habe versucht, dies mit einem realen Beispiel zu vergleichen, das auf einem Projekt basiert, an dem ich arbeitete. Wie immer sind die Unterschiede trivial, aber die Ergebnisse waren etwas unerwartet. Bei den meisten Benchmarks, die ich gesehen habe, ändert die aufgerufene Funktion den übergebenen Wert nicht wirklich. Ich habe ein einfaches str_replace() darauf ausgeführt.
**Pass by Value Test Code:**
$originalString=''; // 1000 pseudo-random digits
function replace($string) {
return str_replace('1', 'x',$string);
}
$output="";
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);
for ($i = 0; $i < 10; $i++ ) {
for ($j = 0; $j < 1000000; $j++) {
$string = $originalString;
$string = replace($string);
}
}
/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "\n" . 'Total Time' .
': ' . $totalTime;
$output .= "\n" . $string;
echo $output;
Der Unterschied beträgt einen Bruchteil einer Millisekunde pro Funktionsaufruf, aber für diesen Anwendungsfall ist die Übergabe per Referenz sowohl in PHP 5 als auch in PHP 7 schneller.
(Hinweis: Die PHP 7-Tests wurden auf einem schnelleren Rechner durchgeführt – PHP 7 ist schneller, aber wahrscheinlich nicht viel schneller.)
Endergebnis! Je größer das Array (oder je größer die Anzahl der Aufrufe), desto größer ist der Unterschied. In diesem Fall ist der Aufruf per Referenz also schneller, da der Wert innerhalb der Funktion geändert wird.
Ansonsten gibt es keinen wirklichen Unterschied zwischen “by reference” und “by value”, der Compiler ist schlau genug, nicht jedes Mal eine neue Kopie zu erstellen, wenn es nicht nötig ist.
Es könnte genauer sein, “Interpreter” statt “Compiler” zu sagen?
– mpet
11. September 2016 um 22:39 Uhr
Wenn Sie Benchmarks erstellen, zeigen Sie bitte die resultierenden Zeitwerte an. Da Sie testen, sollten Sie auch Ihre Behauptung getestet haben, dass es keine Rolle spielt, wenn kein Wert geändert wird. Andernfalls kann ein Leser nicht leicht feststellen, was Sie getestet haben, was Sie einfach behaupten.
– WerkzeugmacherSteve
18. Juli 2020 um 0:04 Uhr
9245900cookie-checkIst in PHP (>= 5.0) die Referenzübergabe schneller?yes
Siehe meine Frage für ein Beispiel, wo Referenzen die Dinge dramatisch verlangsamen können: stackoverflow.com/questions/3117604/…
– John Carter
30. Juni 2010 um 10:24 Uhr