SORU
4 Mart 2015, ÇARŞAMBA


Stackoverflow C boks yapıyor#

C bu iki kod parçaları var#:

İlk

class Program
{
    static Stack<int> S = new Stack<int>();

    static int Foo(int n) {
        if (n == 0)
            return 0;
        S.Push(0);
        S.Push(1);
        ...
        S.Push(999);
        return Foo( n-1 );
    }
}

İkinci

class Program
{
    static Stack S = new Stack();

    static int Foo(int n) {
        if (n == 0)
            return 0;
        S.Push(0);
        S.Push(1);
        ...
        S.Push(999);
        return Foo( n-1 );
    }
}

İkisi de aynı şeyi:

  1. Bir Yığın (ikinci bir nesne yığını bir ilk örneğin <int> genel) oluşturun.

  2. Özyinelemeli olarak çağırır ve bir metot n kez (n >= 0) ve her adımda bas 1000 oluşturulan yığın içinde tamsayılar.

Foo(30000) ilk örnek çalıştırdığımda bir istisna, ancak ikinci örnek Foo(1000), n = 1000 çöker oluşur.

CIL Her iki durumda da üretilen gördüğümde tek fark her itmek için boks kısmıydı:

İlk

IL_0030:  ldsfld     class [System]System.Collections.Generic.Stack`1<int32> Test.Program::S
IL_0035:  ldc.i4     0x3e7
IL_003a:  callvirt   instance void class [System]System.Collections.Generic.Stack`1<int32>::Push(!0)
IL_003f:  nop

İkinci

IL_003a:  ldsfld     class [mscorlib]System.Collections.Stack Test.Program::S
IL_003f:  ldc.i4     0x3e7
IL_0044:  box        [mscorlib]System.Int32
IL_0049:  callvirt   instance void [mscorlib]System.Collections.Stack::Push(object)
IL_004e:  nop

Benim soru: Neden ikinci örneğin yığın CIL önemli aşırı ise, "daha hızlı" ilk daha mı? kaza mı

CEVAP
4 Mart 2015, ÇARŞAMBA


Neden ikinci örneğin yığın CIL önemli aşırı ise, "daha hızlı" ilk daha mı? kaza mı

Bu notunumarasıbu CIL talimatları doğru bir şekilde kullanılacak iş ya da bellek miktarını temsil etmiyor. Tek bir talimat etkisi çok düşük veya çok yüksek darbe olabilir, ÇİL talimatları sayım ölçmek için doğru bir yol değildir.".

Ayrıca CIL infaz ediliyor ne olduğunun da farkına varırlar. Bu TAM da ÇİL gerçek yürütülen yönergeleri çok daha farklı olabilir yani bir optimizasyon aşaması ile gerçek makine talimatları için CIL derler,,.

Genel olmayan bir koleksiyon kullanıyorsun beri ikinci durumda, Push Her çağrı CIL içinde belirlenen tamsayı kutulu olmasını gerektirir.

Bir tamsayı etkili bir nesne oluşturur boks hangi "Int32. sarar Yerine sadece bir yükleme 32-bit tamsayı üzerine yığını, şimdi yüklemek için bir 32-bit tamsayı üzerine yığını, kutu, etkili de yükler bir nesne başvurusu üzerine yığın.

Eğer Çözümü penceresinde bu incelemek, genel ve genel olmayan sürüm oluşturulan CIL öneriyorsun daha dramatik, çok daha önemli arasındaki farkı görebilirsiniz.

Jenerik etkili bunu gibi bir dizi çağrı olarak derler:

0000022c  nop 
            S.Push(25);
0000022d  mov         ecx,dword ptr ds:[03834978h] 
00000233  mov         edx,19h 
00000238  cmp         dword ptr [ecx],ecx 
0000023a  call        71618DD0 
0000023f  nop 
            S.Push(26);
00000240  mov         ecx,dword ptr ds:[03834978h] 
00000246  mov         edx,1Ah 
0000024b  cmp         dword ptr [ecx],ecx 
0000024d  call        71618DD0 
00000252  nop 
            S.Push(27);

Genel olmayan, öte yandan, kutulu nesneleri oluşturmak için, ve bunun yerine derler

00000645  nop 
            S.Push(25);
00000646  mov         ecx,7326560Ch 
0000064b  call        FAAC20B0 
00000650  mov         dword ptr [ebp-48h],eax 
00000653  mov         eax,dword ptr ds:[03AF4978h] 
00000658  mov         dword ptr [ebp FFFFFEE8h],eax 
0000065e  mov         eax,dword ptr [ebp-48h] 
00000661  mov         dword ptr [eax 4],19h 
00000668  mov         eax,dword ptr [ebp-48h] 
0000066b  mov         dword ptr [ebp FFFFFEE4h],eax 
00000671  mov         ecx,dword ptr [ebp FFFFFEE8h] 
00000677  mov         edx,dword ptr [ebp FFFFFEE4h] 
0000067d  mov         eax,dword ptr [ecx] 
0000067f  mov         eax,dword ptr [eax 2Ch] 
00000682  call        dword ptr [eax 18h] 
00000685  nop 
            S.Push(26);
00000686  mov         ecx,7326560Ch 
0000068b  call        FAAC20B0 
00000690  mov         dword ptr [ebp-48h],eax 
00000693  mov         eax,dword ptr ds:[03AF4978h] 
00000698  mov         dword ptr [ebp FFFFFEE0h],eax 
0000069e  mov         eax,dword ptr [ebp-48h] 
000006a1  mov         dword ptr [eax 4],1Ah 
000006a8  mov         eax,dword ptr [ebp-48h] 
000006ab  mov         dword ptr [ebp FFFFFEDCh],eax 
000006b1  mov         ecx,dword ptr [ebp FFFFFEE0h] 
000006b7  mov         edx,dword ptr [ebp FFFFFEDCh] 
000006bd  mov         eax,dword ptr [ecx] 
000006bf  mov         eax,dword ptr [eax 2Ch] 
000006c2  call        dword ptr [eax 18h] 
000006c5  nop 

Burada boks önemini görebilirsiniz.

Senin durumunda bir tamsayı boks kutulu nesne başvurularını yığının üstüne yüklenir neden olur. Benim sistem, bu neden bir stackoverflow üzerinde herhangi bir çağrı daha büyük Foo(127) (32 bit), hangi önerdiği tamsayılar ve kutulu nesne başvurularını (4 bayt her biri) tüm tutuluyor yığında olarak 127*1000*8==1016000, tehlikeli kapatmak için varsayılan değer 1) parçacığı yığın boyutu .NET uygulamaları.

Genel sürüm kullanırken, kutulu bir nesne yok beri, tamsayılar tüm yığında saklı olmak zorunda değil, ve aynı kayıt tekrar ediliyor. Bu recurse önemli ölçüde daha fazla (^sağlar . Yukarı yığın kullanmadan önce benim sistemi 40000).

Bu da/x 64 86, farklı bir JİT olarak CLR sürümü ve platform bağımlı olacak, unutmayın.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Marques Brownlee

    Marques Brow

    21 Mart 2008
  • RawBrahs

    RawBrahs

    28 Aralık 2010
  • Vladimir Jenko

    Vladimir Jen

    1 Mart 2010