2010-10-12 7 views
6

Ist es schneller Variablen innerhalb einer Schleife oder außerhalb einer Schleife zu deklarieren? Zum Beispiel:Schneller zum Deklarieren von Variablen innerhalb einer Schleife oder außerhalb einer Schleife?

' Declaration inside of the loop 
For each item in items 
    Dim newVariable as String = GetAString() 
Next 

' Declaration outside of the loop 
Dim newVariable as String = String.Empty 
For each item in items 
    newVariable = GetAString() 
Next 

Welcher ist schneller? Warum? Ich nehme an, dass Letzteres schneller ist, weil es einfach den gleichen "Zeiger" wiederbenutzt, um einen neuen Wert hinter den Kulissen zu referenzieren, anstatt bei jeder Wiederholung einen neuen Zeiger zu erzeugen, richtig? Kann jemand etwas ausarbeiten?

Dank

Aktualisiert:

Der Compiler intelligent genug ist, den Code zu optimieren, wenn die Intermediate Language erzeugen. Es verschiebt die Variablendeklarationen an den Anfang der Methode. Unten ist die declartions innerhalb der IL nach der Kompilierung:

.locals init ([0] string newVariable2, 
      [1] int32 i, 
      [2] string newVariable, 
      [3] int32 V_3, 
      [4] int32 VB$CG$t_i4$S0) 

Hier wird die gesamte IL für die Interessenten ist:

.method private instance void Form1_Load(object sender, 
              class [mscorlib]System.EventArgs e) cil managed 
{ 
    // Code size  55 (0x37) 
    .maxstack 2 
    .locals init ([0] string newVariable2, 
      [1] int32 i, 
      [2] string newVariable, 
      [3] int32 V_3, 
      [4] int32 VB$CG$t_i4$S0) 
    IL_0000: nop 
    IL_0001: ldc.i4.0 
    IL_0002: stloc.1 
    IL_0003: ldarg.0 
    IL_0004: callvirt instance string WindowsApplication1.TestVariableDeclaration::getstring() 
    IL_0009: stloc.2 
    IL_000a: nop 
    IL_000b: ldloc.1 
    IL_000c: ldc.i4.1 
    IL_000d: add.ovf 
    IL_000e: stloc.1 
    IL_000f: ldloc.1 
    IL_0010: ldc.i4  0x989680 
    IL_0015: stloc.s VB$CG$t_i4$S0 
    IL_0017: ldloc.s VB$CG$t_i4$S0 
    IL_0019: ble.s  IL_0003 
    IL_001b: ldc.i4.0 
    IL_001c: stloc.3 
    IL_001d: ldarg.0 
    IL_001e: callvirt instance string WindowsApplication1.TestVariableDeclaration::getstring() 
    IL_0023: stloc.0 
    IL_0024: nop 
    IL_0025: ldloc.3 
    IL_0026: ldc.i4.1 
    IL_0027: add.ovf 
    IL_0028: stloc.3 
    IL_0029: ldloc.3 
    IL_002a: ldc.i4  0x989680 
    IL_002f: stloc.s VB$CG$t_i4$S0 
    IL_0031: ldloc.s VB$CG$t_i4$S0 
    IL_0033: ble.s  IL_001d 
    IL_0035: nop 
    IL_0036: ret 
} // end of method TestVariableDeclaration::Form1_Load 
+1

Vielleicht würde der Compiler es optimieren? Bester Tipp: Starten Sie Ihre IDE, instanziieren Sie eine Stoppuhr und führen Sie einige tausend Iterationen jeder Version aus, um zu sehen, ob es wirklich einen Unterschied gibt. –

+0

Gute Idee! Brb mit den Ergebnissen. – Moderator71

+4

Versuchen Sie, ein tatsächliches Leistungsproblem zu lösen, oder sind Sie nur gelangweilt und spielen mit Mikro-Optimierungen, die nie einen sinnvollen Unterschied in einer realen Welt-App ergeben würden? – JohnFx

Antwort

11

Ich stimme Kevins Antwort zu, definieren Variablen, wo sie Bedeutung haben. Sorgen Sie sich über Optimierungen, wenn sie sich selbst präsentieren, und Sie wissen, dass eine Variablendeklaration das Problem ist. Allerdings sollten Sie die folgenden zwei Code

void Test1() 
{ 
    foreach (int i in Enumerable.Range(0,10)) 
    { 
     string s = GetString(); 
     Console.WriteLine(s); 
    } 
} 

void Test2() 
{ 
    string s; 
    foreach (int i in Enumerable.Range(0,10)) 
    { 
     s = GetString(); 
     Console.WriteLine(s); 
    } 
} 

Und ihre erzeugte IL:

Test1: 
IL_0000: ldc.i4.0  
IL_0001: ldc.i4.s 0A 
IL_0003: call  System.Linq.Enumerable.Range 
IL_0008: callvirt System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator 
IL_000D: stloc.1  
IL_000E: br.s  IL_0024 
IL_0010: ldloc.1  
IL_0011: callvirt System.Collections.Generic.IEnumerator<System.Int32>.get_Current 
IL_0016: pop   
IL_0017: ldarg.0  
IL_0018: call  UserQuery.GetString 
IL_001D: stloc.0  
IL_001E: ldloc.0  
IL_001F: call  System.Console.WriteLine 
IL_0024: ldloc.1  
IL_0025: callvirt System.Collections.IEnumerator.MoveNext 
IL_002A: brtrue.s IL_0010 
IL_002C: leave.s  IL_0038 
IL_002E: ldloc.1  
IL_002F: brfalse.s IL_0037 
IL_0031: ldloc.1  
IL_0032: callvirt System.IDisposable.Dispose 
IL_0037: endfinally 
IL_0038: ret   

Test2: 
IL_0000: ldc.i4.0  
IL_0001: ldc.i4.s 0A 
IL_0003: call  System.Linq.Enumerable.Range 
IL_0008: callvirt System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator 
IL_000D: stloc.1  
IL_000E: br.s  IL_0024 
IL_0010: ldloc.1  
IL_0011: callvirt System.Collections.Generic.IEnumerator<System.Int32>.get_Current 
IL_0016: pop   
IL_0017: ldarg.0  
IL_0018: call  UserQuery.GetString 
IL_001D: stloc.0  
IL_001E: ldloc.0  
IL_001F: call  System.Console.WriteLine 
IL_0024: ldloc.1  
IL_0025: callvirt System.Collections.IEnumerator.MoveNext 
IL_002A: brtrue.s IL_0010 
IL_002C: leave.s  IL_0038 
IL_002E: ldloc.1  
IL_002F: brfalse.s IL_0037 
IL_0031: ldloc.1  
IL_0032: callvirt System.IDisposable.Dispose 
IL_0037: endfinally 
IL_0038: ret 

einen Unterschied sehen? Diese Compilerleute, sie sind schlau.

+0

Die Verwendung der Stoppuhr war nicht sehr nützlich. Ich habe unterschiedliche Ergebnisse, aber die IL zu betrachten war wohltuend. Im Wesentlichen verschiebt der Compiler die Deklaration an den Anfang der Methode in der IL. Ich werde meinen Beitrag bearbeiten, um eine Klarstellung der IL zu ermöglichen. – Moderator71

2

Ich könnte mir vorstellen, dass der Optimierer weiß, dass diese gleich sind und daher heraus, dass sie drehen die gleiche Leistung zu haben. Es könnte aber nicht sein. Sie können entweder den Objektcode oder die Maßzahl prüfen.

4

Weder. Sie erstellen immer noch eine neue Zeichenfolge in jeder Iteration der Schleife, so dass sie identisch sind. Selbst wenn es einen gibt, ist das, was du nimmst, in dem großen Umfang der Dinge unglaublich vernachlässigbar.

Die Bereichsdeklaration der Variablen wird sich ändern, und wenn Sie sie außerhalb der Schleife nicht benötigen, sollten Sie sie innen platzieren.