2009-06-18 10 views

Odpowiedz

13

Kompilator nadal używa instrukcji IL newarr, aby CLR nadal inicjował tablicę.

Inicjowanie kolekcji to tylko kompilator magia - CLR nic o tym nie wie, więc nadal będzie zakładać, że musi to zrobić.

Jednak powinno to być naprawdę, bardzo szybkie - wystarczy wyczyścić pamięć. Wątpię, by w wielu sytuacjach było to znaczące obciążenie.

+0

Interesujące. Zastanawiam się, czy to podejście "wymazanie pamięci" do inicjowania macierzy jest jednym z powodów, dla których konstrukcje nie obsługują jawnie konstruktorów domyślnych lub inicjalizatorów członów. Utrudniłoby inicjalizację macierzy. – LBushkin

+1

Tak, to dużo. W rzeczywistości, struktury w IL * do * obsługują konstruktory bez parametrów, ale będą one wywoływane tylko w pewnych sytuacjach. –

+0

Zobacz http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types-and-parameterless-constructors.aspx, aby uzyskać więcej informacji. –

10

Szybki test:

 string[] arr1 = 
     { 
      "A","B","C","D" 
     }; 
     arr1.GetHashCode(); 

     string[] arr2 = new string[4]; 
     arr2[0] = "A"; 
     arr2[1] = "B"; 
     arr2[2] = "C"; 
     arr2[3] = "D"; 

     arr2.GetHashCode(); 

wyniki w tym IL (uwaga, są zarówno identyczne)

IL_0002: newarr  [mscorlib]System.String 
    IL_0007: stloc.2 
    IL_0008: ldloc.2 
    IL_0009: ldc.i4.0 
    IL_000a: ldstr  "A" 
    IL_000f: stelem.ref 
    IL_0010: ldloc.2 
    IL_0011: ldc.i4.1 
    IL_0012: ldstr  "B" 
    IL_0017: stelem.ref 
    IL_0018: ldloc.2 
    IL_0019: ldc.i4.2 
    IL_001a: ldstr  "C" 
    IL_001f: stelem.ref 
    IL_0020: ldloc.2 
    IL_0021: ldc.i4.3 
    IL_0022: ldstr  "D" 
    IL_0027: stelem.ref 
    IL_0028: ldloc.2 
    IL_0029: stloc.0 
    IL_002a: ldloc.0 
    IL_002b: callvirt instance int32 [mscorlib]System.Object::GetHashCode() 
    IL_0030: pop 
    IL_0031: ldc.i4.4 
    IL_0032: newarr  [mscorlib]System.String 
    IL_0037: stloc.1 
    IL_0038: ldloc.1 
    IL_0039: ldc.i4.0 
    IL_003a: ldstr  "A" 
    IL_003f: stelem.ref 
    IL_0040: ldloc.1 
    IL_0041: ldc.i4.1 
    IL_0042: ldstr  "B" 
    IL_0047: stelem.ref 
    IL_0048: ldloc.1 
    IL_0049: ldc.i4.2 
    IL_004a: ldstr  "C" 
    IL_004f: stelem.ref 
    IL_0050: ldloc.1 
    IL_0051: ldc.i4.3 
    IL_0052: ldstr  "D" 
    IL_0057: stelem.ref 
    IL_0058: ldloc.1 
    IL_0059: callvirt instance int32 [mscorlib]System.Object::GetHashCode() 
+0

+1 Dla testu. –

1

Pobiegłem krótki test na instantianting tablicę używając opisać składnię i znalazł to tworzenie instancji z wartościami innymi niż domyślne trwało około 2,2 raza dłużej niż chwilowość z wartościami domyślnymi.

Po przełączeniu i utworzeniu instancji z wartościami domyślnymi zajmuje to mniej więcej tyle samo czasu.

Rzeczywiście, gdy przyjrzałem się dekompilacji, okazało się, że to, co się dzieje, jest inicjowane przez macierz, a następnie zapełniane są dowolnymi wartościami, które nie są domyślne.

instancji z wartościami innych niż domyślne:

  bool[] abPrimes = new[] { 
       true, true 
      }; 
0000007e mov   edx,2 
00000083 mov   ecx,79114A46h 
00000088 call  FD3006F0 
0000008d mov   dword ptr [ebp-64h],eax 
00000090 mov   eax,dword ptr [ebp-64h] 
00000093 mov   dword ptr [ebp-54h],eax 
00000096 mov   eax,dword ptr [ebp-54h] 
00000099 cmp   dword ptr [eax+4],0 
0000009d ja   000000A4 
0000009f call  76A9A8DC 
000000a4 mov   byte ptr [eax+8],1 
000000a8 mov   eax,dword ptr [ebp-54h] 
000000ab cmp   dword ptr [eax+4],1 
000000af ja   000000B6 
000000b1 call  76A9A8DC 
000000b6 mov   byte ptr [eax+9],1 
000000ba mov   eax,dword ptr [ebp-54h] 
000000bd mov   dword ptr [ebp-40h],eax 

instancji wartości domyślne:

bool[] abPrimes2 = new[] { 
       false, false 
      }; 
000000c0 mov   edx,2 
000000c5 mov   ecx,79114A46h 
000000ca call  FD3006F0 
000000cf mov   dword ptr [ebp-68h],eax 
000000d2 mov   eax,dword ptr [ebp-68h] 
000000d5 mov   dword ptr [ebp-54h],eax 
000000d8 mov   eax,dword ptr [ebp-54h] 
000000db mov   dword ptr [ebp-5Ch],eax 
0

Nie jest to możliwe w celu uniknięcia inicjowania każdą szczelinę tablicy wartości domyślnej co najmniej poziomu IL.

Łańcuch jest KLASĄ, a nie strukturą.

Oznacza to, że A, B, C, D i sarray mogą być przechowywane w dowolnej pozycji. A, B, C i D mogą być pobierane z puli Intern, ponieważ odwołanie do obiektu może być dynamiczne.

Uważam jednak, że JIT mógłby na tyle sprytny, aby zmniejszyć połowę tych kosztów ogólnych.

PS. Przedwczesna optymalizacja jest źródłem wszelkiego zła.