php foreach, warum die Verwendung von Pass by Reference eines Arrays ist schnell?

8

Unten ist ein Test von php foreach loop eines großen Arrays, ich dachte, dass, wenn sich die $v nicht ändern, die echte Kopie wegen copy on write nicht passieren wird, aber warum es ist schnell, wenn durch Referenz gehen?

Code 1:

%Vor%

Aber dieses Mal ist die Verwendung von Weitergabe als Referenz langsam.

Code 2:

%Vor%

Kann jemand erklären, warum die Übergabe per Referenz in Code1 schnell ist, aber langsam in Code2?

Bearbeiten: Bei Code 2 macht der count($a) den Hauptunterschied, also ist die Zeit der Schleife fast gleich.

    
xdazz 16.10.2011, 19:03
quelle

2 Antworten

7
  

Ich dachte, wenn die $v sich nicht ändern [ foreach($a as $v) ], wird die echte Kopie nicht passieren wegen Kopieren beim Schreiben , aber warum ist es schnell beim Referenzieren?

Die Auswirkung ist nicht auf $v , sondern auf $a , dem riesigen Array. Sie übergeben es entweder als Wert oder als Verweis auf die Funktion. Innerhalb der Funktion ist es dann Wert (test1) oder Referenz (test2).

Sie haben zwei Codes (Code 1 und Code 2).

Code 1: Verwendet foreach . Mit foreach haben Sie zwei Möglichkeiten: Iterieren Sie über einen Wert oder eine Referenz ( Beispiel ). Wenn Sie über einen Wert iterieren, wird die Iteration für eine Kopie des Werts ausgeführt. Wenn Sie über eine Referenz iterieren, wird keine Kopie erstellt.

Wenn Sie die Referenz in test2 verwenden, ist es schneller. Die Werte müssen nicht kopiert werden. Aber in test1 übergeben Sie das Array als Wert, das Array wird kopiert.

Code 2: Verwendet for . Denn tut eigentlich nichts hier. In beiden Fällen. Sie greifen auf die Variable zu und lesen den Wert aus dem Array. Das ist ziemlich egal, egal ob es sich um eine Referenz oder eine Kopie handelt (dank der Kopie beim Schreiben Optimierung in PHP).

Sie könnten sich jetzt fragen, warum ist ein Unterschied in Code 2. Der Unterschied ist nicht wegen for , sondern wegen count . Wenn Sie einen Verweis auf count weitergeben, erstellt PHP intern eine Kopie davon, weil count eine Kopie benötigt, keine Referenz.

Lesen Sie auch: Verwenden Sie keine PHP-Referenzen von Johannes Schlüter

Ich habe auch eine Reihe von Tests zusammengestellt. Aber ich setze Code genauer in die Testfunktionen.

  • Leer - Was ist der Unterschied beim Aufruf der Funktion?
  • Anzahl - Macht count einen Unterschied?
  • For - Was passiert nur mit for (nicht count )?
  • Foreach - Nur foreach - bricht sogar beim ersten Element.

Jeder Test besteht aus zwei Versionen, einer mit dem Namen _copy (Übergabe des Arrays als Kopie an die Funktion) und einer namens _ref (Übergabe des Arrays als Referenz).

Es ist nicht immer so, dass diese Mikro-Benchmarks Ihnen die Wahrheit sagen, aber wenn Sie in der Lage sind, bestimmte Punkte zu isolieren, können Sie gut begründen, dass nicht for , aber count die Wirkung hatten :

%Vor%

Ausgabe:

%Vor%     
hakre 16.10.2011, 20:59
quelle
3

Eigentlich stimme ich ein wenig mit der ersten Antwort überein. Vor allem, wie die Kommentare sagen, sind die Tests nicht gleich. Hier sind die vollständig isolierten Tests, die NUR die Schleifen testen.

Version 1:

%Vor%

Version 2:

%Vor%

Beachten Sie, dass in der vollständig isolierten Form die zweiten Tests KEINE Unterschiede zeigen, während die erste dies tut. Warum?

Die Antwort ist, dass das Array einen internen Zeiger für Dinge wie foreach hat. Es kann auf Aufrufe wie aktuell zugegriffen werden. Wenn Sie foreach mit einer Referenz arbeiten, werden die Zeiger des ursprünglichen Arrays verwendet. Wenn Sie den Wert übergeben, müssen die Array-Interna kopiert werden, sobald der Foreach ausgeführt wird, auch wenn die Werte irgendwie von der Engine beibehalten werden. Also, die Strafe.

    
Sajid 16.10.2011 21:06
quelle

Tags und Links