2009-07-15 12 views
0

Gibt es einen Unterschied in der Laufzeit der folgenden zwei Schnipsel?gibt es einen Unterschied in der Laufzeit der folgenden:

SNIPPET 1:

for (Object obj : collection) { 
    step1(obj); 
    step2(obj); 
    step3(obj); 
} 

SNIPPET 2:

for (Object obj : collection) { 
    step1(obj); 
} 

for (Object obj : collection) { 
    step2(obj); 
} 

for (Object obj : collection) { 
    step3(obj); 
} 
+0

Abhängig von der Implementierung von 'step1',' step2' und 'step3', kompiliert der Compiler die letztere zu demselben (Byte) Code wie der erstere. Aber, warum tust du es nicht selbst? – Stephan202

+0

Nein, würde es nicht. Die Anrufe werden in unterschiedlichen Aufträgen getätigt. Wenn Objekte a, b, c usw. sind. Die Aufrufe sind a1, a2, a3, b1, b2, b3 usw. im ersten Beispiel, aber sie sind a1, b1, a2, b2, a3, c3 im zweiten Beispiel. – FogleBird

+0

Sie haben das gleiche Big-O, aber im Gegensatz zu den meisten nachfolgenden Ansprüchen ist es unmöglich zu wissen, welche zur Laufzeit schneller sind, ohne zu wissen, was step1, step2 und step3 tun. Es gibt Code-Cache-Kohärenz, Daten-Cache-Kohärenz, Genauigkeit der Verzweigungsvorhersage ... eine beliebige Anzahl von Dingen, die die Laufzeitleistung verändern können. Timing es selbst ist die einzige Möglichkeit zu "wissen", und trotzdem sind die Ergebnisse immer noch spezifisch für Ihre Hardware. –

Antwort

1

Natürlich. Das erste Snippet durchläuft die Sammlung nur einmal, während das zweite Snippet es drei Mal wiederholt. Das zweite Snippet verletzt ebenfalls das DRY-Prinzip.

+0

Intuitiv scheint es, dass Sie Recht haben, aber ich sehe keinen Unterschied in der Laufzeitleistung. Jedes Snippet führt 3N Schritte aus, wobei N die Größe der Sammlung ist. Einige Sprachen haben Overhead mit Iteration verbunden, aber wenn wir das ignorieren, sehe ich keinen großen Unterschied zwischen den beiden. – os111

+0

Nun, wenn Sie den Iterationsunterschied ignorieren, welchen anderen Unterschied würde es geben? Sie sind dann die gleichen. – ryeguy

+0

+1 für DRY ...Außerdem, wenn es sich um eine veränderbare Sammlung handelt (oder ein Objekt, das Iterable implementiert, aber nicht wirklich eine Sammlung ist), könnten Sie verschiedene Operationen für jedes Objekt erhalten. – kdgregory

0

Wenn Sie nach einer Sprache fragen, sollte SNIPPET 1 schneller sein.

0

Die Iterationen werden 3 Mal durchgeführt.

Sie werden auch Schritt 1 (Obj) n Mal, dann Schritt2 (Obj) n mal, dann Schritt3 (Obj) n mal.

0

Wenn einer Ihrer Methodenaufrufe eine Ausnahme auslöst, sagen wir Schritt1 in der Mitte der Iteration, dann stoppt die zweite Version früher als die erste. Aber wenn Schritt3 eine Ausnahme für das erste Element auslöst, ist die erste Version schneller. Die beiden Versionen sind also nicht semantisch äquivalent.

0

Gibt es einen Unterschied? Na sicher.

Gibt es einen Unterschied, der zählt? Es hängt alles ab.

Wenn StepN() ein paar Nanosekunden dauert, dann ja. Sonst wahrscheinlich nicht.

0

Fragen Sie speziell nach Leistung?

In diesem Fall hängt die Antwort darauf, wie schnell die Iterators Sammlung ist: Wenn Next() eine teuere Operation für diesen speziellen Iterator ist, dann zahlen Sie, dass die Kosten für N-mal in der ersten Version und 3N mal im letzteren. Dies ist unbedeutend, wenn Ihre Sammlung ein Vektor ist, aber ernster, wenn Ihre Sammlung z. B. eine Schnittstelle zu einer langsamen Datei-E/A-Operation ist.