mühürlü sınıfları gerçekten performans Faydaları sunuyor musunuz?

oy
118

Ben ekstra performans yararlanmak için mühürlü olarak size sınıfları işaretlemek gerektiğini söylüyorlar optimizasyon ipuçları bir sürü rastlamak var.

Ben performans farkı kontrol etmek için bazı testler yaptım ve hiçbiri bulundu. Yanlış bir şey mi yapıyorum? Ben mühürlü sınıfları daha iyi sonuçlar verecektir davayı eksik?

Herkes testler ve bir fark gören var mı?

Beni öğrenmesine yardımcı :)

Oluştur 05/08/2008 saat 13:00
kaynak kullanıcı
Diğer dillerde...                            


11 cevaplar

oy
133

Cevap hayır, mühürlü sınıfları olmayan mühürlü daha iyi bir performans yok edilir.

Sorun aşağı gelir callvs callvirtIL op kodları. Calldaha hızlıdır callvirtve callvirtnesne sınıflandırma olup olmadığını bilmiyorsanız zaman ağırlıklı kullanılır. Yani insanlar bir sınıf mühür, tüm op kodları değişecektir farz calvirtsetmek callsve daha hızlı olacaktır.

Maalesef callvirtboş başvuruları için denetimi gibi çok yararlı hale başka şeyler yapar. Bu sınıf zarflanmış olduğunda bile, başvuru hala boş olabilir anlamına gelir ve bu nedenle, bir callvirtihtiyaç vardır. Sen (sınıf mühür gerek kalmadan) bu sorunun üstesinden gelebilirsiniz ama biraz anlamsız hale gelir.

Yapılar kullanmak callonlar sınıflandırma edilemez ve boş asla çünkü.

Daha fazla bilgi için bu soruya bakın:

Çağrı ve callvirt

Cevap 24/12/2008 saat 03:09
kaynak kullanıcı

oy
46

onlar daha da uzatılabilir yolu yoktur çünkü jitter bazen mühürlü sınıflarında yöntemlere olmayan sanal aramaları kullanacaktır.

Orada sanal / nonvirtual çağıran tipine ilişkin karmaşık kurallar vardır ve ben bütün bu yüzden gerçekten onları sizin için ana hatlarıyla edemez onları bilmiyorum ama mühürlü sınıfları ve sanal yöntemler için google eğer konu hakkında bazı makaleler bulabilirsiniz.

Optimizasyonun bu seviyede elde edeceği performans yararına her türlü son çare olarak kabul edilmesi gerektiğini unutmayın kod düzeyinde optimize önce hep algoritmik düzeyde optimize eder.

: İşte bir bağlantı bu söz var mühürlü anahtar kelimeyi Rambling

Cevap 05/08/2008 saat 13:32
kaynak kullanıcı

oy
20

Bildiğim kadarıyla, performans yarar garantisi yoktur. Ama var bazı özel koşullar altında performans ceza azaltmak için bir şans mühürlü yöntemle. (kapalı sınıfı mühürlenecek tüm yöntemleri sağlar.)

Ama derleyici uygulama ve yürütme ortamına bağlı.


ayrıntılar

Modern CPU'lar çoğu performansını artırmak için uzun boru hattı yapısını kullanır. İşlemci bellekten daha inanılmaz hızlı olduğu için, işlemci boru hattını hızlandırmak için bellekten kod ön getirmek vardır. Kod doğru zamanda hazır değilse, boru hatları boşta olacak.

Denilen büyük bir engel vardır dinamik bir gönderme bu 'önalımı' optimizasyonu bozar. Sen sadece bir şartlı dallanma olarak bu anlayabiliriz.

// Value of `v` is unknown,
// and can be resolved only at runtime.
// CPU cannot know code to prefetch,
// so just prefetch one of a() or b().
// This is *speculative execution*.
int v = random();
if (v==1) a();
else b();

Giderilene kadar sonraki kod pozisyonu bilinmediği için CPU bu durumda yürütmek için bir sonraki kod önceden getirmek olamaz. Yani bu yapar tehlike boru hattı boşta neden olur. Ve boşta tarafından performans cezası regular büyük.

Benzer şey yazdırma metodu durumunda gerçekleşir. Derleyici akım yöntemi çağrısı için uygun yöntem geçersiz kılma belirleyebilir, ama bazen imkansız. Bu durumda, uygun yöntem yalnızca çalışma zamanında belirlenebilir. Bu dinamik yazılan dillerin temel nedeni statik olarak yazılan dillerin genellikle daha yavaştır, aynı zamanda dinamik sevkinden bir durumdur ve.

(Son Intel'in x86 çipleri dahil) Bazı CPU denilen tekniği kullanır spekülatif yürütme bile durumla ilgili boru hattını kullanmak. Sadece yürütme yolunun birini önceden getirmek. Ancak bu yöntemin isabet oranı o kadar yüksek değildir. Ve spekülasyon arızası da büyük performans kaybına yapar boru hattı durak neden olur. (Bu işlemci uygulaması ile tamamen size bağlıdır. enerjiden tasarruf etmek optimizasyonu bu tür değil gibi bazı mobil işlemci bilinir)

Temelde, C # bir statik olarak derlenmiş bir dildir. Ama her zaman değil. Ben tam durumunu bilmiyorum ve bu tamamen derleyici uygulamasına bağlıdır. Bazı derleyici yöntemi olarak işaretlenmişse, bu yöntem, geçersiz kılma engelleyerek dinamik dağıtım olasılığını ortadan kaldırır sealed. Aptal derleyiciler olmayabilir. Bu performans faydadır sealed.


Bu cevap ( Neden daha hızlı? Bir sırasız dizilerde daha sıralanmış diziyi işlenmesidir çok daha iyi şube kestirimi tarif edilir).

Cevap 03/02/2011 saat 16:22
kaynak kullanıcı

oy
18

Güncelleme: .NET Çekirdek 2.0 ve .NET Desktop 4.7.1 itibariyle CLR şimdi devirtualization destekler. Mühürlü sınıflarında yöntemleri almak ve doğrudan görüşmeleri ile sanal çağrıları yerini alabilir - ve bunu yapmak için güvenli anlamaya eğer o da mühürlü olmayan sınıflar için bunu yapabilirsiniz.

Böyle bir durumda (CLR aksi güvenli algılayamadı kapalı bir sınıf devirtualise kadar) olarak, kapalı bir sınıf aslında performans yararı çeşit sunmalıdır.

Yani ben endişelenmeye değer olacağını düşünüyorum olmaz dedi sürece kodunu zaten profilli ve böyle milyonlarca kat, ya da bir şey çağrıldığını özellikle sıcak yolunda olduğunun belirlenmesi etmişti:

https://blogs.msdn.microsoft.com/dotnet/2017/06/29/performance-improvements-in-ryujit-in-net-core-and-net-framework/


Orijinal Cevap:

Aşağıdaki test programı yaptı, sonra MSIL kodu yayılan neler olduğunu görmek için yansıtıcı kullanarak bunu bozulamaz.

public class NormalClass {
    public void WriteIt(string x) {
        Console.WriteLine("NormalClass");
        Console.WriteLine(x);
    }
}

public sealed class SealedClass {
    public void WriteIt(string x) {
        Console.WriteLine("SealedClass");
        Console.WriteLine(x);
    }
}

public static void CallNormal() {
    var n = new NormalClass();
    n.WriteIt("a string");
}

public static void CallSealed() {
    var n = new SealedClass();
    n.WriteIt("a string");
}

Her durumda, C # derleyicisi (Release inşa yapılandırmasında Görsel stüdyo 2010) aşağıdaki gibidir özdeş MSIL, yayar:

L_0000: newobj instance void <NormalClass or SealedClass>::.ctor()
L_0005: stloc.0 
L_0006: ldloc.0 
L_0007: ldstr "a string"
L_000c: callvirt instance void <NormalClass or SealedClass>::WriteIt(string)
L_0011: ret 

Insanlar mühürlü söylemek sık alıntılanan nedeni derleyici kullanabilirsiniz böylece sınıf yeri etkilenmez bilir ve olmasıdır performans yararları sağlar callyerine callvirtyukarıda kanıtlanmış gibi vb virtuals, denetlemek zorunda değildir gibi bu değil doğru.

Bir sonraki düşünce MSIL aynı olsa da, belki de JIT derleyicisi davranır farklı sınıfları mühürlü bu?

Görsel stüdyo ayıklayıcı altında bir sürüm derlemesi koştu ve decompiled x86 çıkışını gördü. Her iki durumda da, x86 kod sınıf adları ve işlev bellek adresleri (elbette farklı olmalıdır) hariç olmak üzere, aynıydı. İşte burada

//            var n = new NormalClass();
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  sub         esp,8 
00000006  cmp         dword ptr ds:[00585314h],0 
0000000d  je          00000014 
0000000f  call        70032C33 
00000014  xor         edx,edx 
00000016  mov         dword ptr [ebp-4],edx 
00000019  mov         ecx,588230h 
0000001e  call        FFEEEBC0 
00000023  mov         dword ptr [ebp-8],eax 
00000026  mov         ecx,dword ptr [ebp-8] 
00000029  call        dword ptr ds:[00588260h] 
0000002f  mov         eax,dword ptr [ebp-8] 
00000032  mov         dword ptr [ebp-4],eax 
//            n.WriteIt("a string");
00000035  mov         edx,dword ptr ds:[033220DCh] 
0000003b  mov         ecx,dword ptr [ebp-4] 
0000003e  cmp         dword ptr [ecx],ecx 
00000040  call        dword ptr ds:[0058827Ch] 
//        }
00000046  nop 
00000047  mov         esp,ebp 
00000049  pop         ebp 
0000004a  ret 

Sonra belki ayıklayıcı altında çalışan düşünce daha az agresif optimizasyonu yapmak neden olur?

Sonra tek başına bırakma herhangi ayıklama ortamlarının yürütülebilir dışında inşa ran ve program tamamlandıktan sonra kırmak ve JIT derlenmiş x86 kod dissasembly görüntülemek için WinDBG + SOS kullandı.

Aşağıdaki kod görebileceğiniz gibi ayıklayıcısını dışında çalıştırırken, JIT derleyicisi daha agresif olduğunu ve inlined etmiştir WriteItdüz arayan içine yöntemi. Önemli olan, ancak bir mühürlü olmayan sınıf karşı sızdırmaz çağrı zaman aynı olmasıdır. Mühürlü veya kapatılmamış sınıf arasındaki hiçbir fark yoktur.

Normal bir sınıf ararken İşte burada:

Normal JIT generated code
Begin 003c00b0, size 39
003c00b0 55              push    ebp
003c00b1 8bec            mov     ebp,esp
003c00b3 b994391800      mov     ecx,183994h (MT: ScratchConsoleApplicationFX4.NormalClass)
003c00b8 e8631fdbff      call    00172020 (JitHelp: CORINFO_HELP_NEWSFAST)
003c00bd e80e70106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c00c2 8bc8            mov     ecx,eax
003c00c4 8b1530203003    mov     edx,dword ptr ds:[3302030h] ("NormalClass")
003c00ca 8b01            mov     eax,dword ptr [ecx]
003c00cc 8b403c          mov     eax,dword ptr [eax+3Ch]
003c00cf ff5010          call    dword ptr [eax+10h]
003c00d2 e8f96f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c00d7 8bc8            mov     ecx,eax
003c00d9 8b1534203003    mov     edx,dword ptr ds:[3302034h] ("a string")
003c00df 8b01            mov     eax,dword ptr [ecx]
003c00e1 8b403c          mov     eax,dword ptr [eax+3Ch]
003c00e4 ff5010          call    dword ptr [eax+10h]
003c00e7 5d              pop     ebp
003c00e8 c3              ret

Kapalı bir sınıf vs:

Normal JIT generated code
Begin 003c0100, size 39
003c0100 55              push    ebp
003c0101 8bec            mov     ebp,esp
003c0103 b90c3a1800      mov     ecx,183A0Ch (MT: ScratchConsoleApplicationFX4.SealedClass)
003c0108 e8131fdbff      call    00172020 (JitHelp: CORINFO_HELP_NEWSFAST)
003c010d e8be6f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c0112 8bc8            mov     ecx,eax
003c0114 8b1538203003    mov     edx,dword ptr ds:[3302038h] ("SealedClass")
003c011a 8b01            mov     eax,dword ptr [ecx]
003c011c 8b403c          mov     eax,dword ptr [eax+3Ch]
003c011f ff5010          call    dword ptr [eax+10h]
003c0122 e8a96f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c0127 8bc8            mov     ecx,eax
003c0129 8b1534203003    mov     edx,dword ptr ds:[3302034h] ("a string")
003c012f 8b01            mov     eax,dword ptr [ecx]
003c0131 8b403c          mov     eax,dword ptr [eax+3Ch]
003c0134 ff5010          call    dword ptr [eax+10h]
003c0137 5d              pop     ebp
003c0138 c3              ret

Bana göre bu oradaki kanıtını sağlar olamaz :-) ... Ben şimdi mutluyum düşünüyorum mühürlü olmayan sınıfları vs mühürlü üzerinde yöntemleri çağırmadan arasında herhangi bir performans gelişme

Cevap 20/02/2012 saat 21:45
kaynak kullanıcı

oy
4

Bir sınıf İşaretleme sealedherhangi bir performans etkisi olması gerekir.

Durumlar vardır cscbir yayarlar gerekebilir callvirtyerine bir işlem kodu callişlem kodu. Ancak, bu durumlar nadirdir görünüyor.

Ve JIT için aynı olmayan sanal işlev çağrısı yayarlar gerekir geliyor bana callvirtonun için olur o call, (henüz) sınıfı herhangi alt sınıfları yok biliyorsa. Yöntemin tek uygulama varsa, vtable-sadece doğrudan bir uygulaması dediğimiz dan adresini yüklenirken anlamı yok. Hatta, JIT hatta işlevini satır içine alabilirsiniz.

Bir alt sınıf ise, çünkü JIT parçası üzerinde bir kumar biraz edilir daha sonra yüklenen, JIT gerçek sanal çağrıyı yayan o makine kodunu atmak ve tekrar kod derlemek zorunda kalacaktır. Benim tahminim bu pratikte sık olmaz olduğunu.

(Ve evet, VM tasarımcıları gerçekten agresif bu küçük performans kazanır takip yoktur.)

Cevap 20/11/2009 saat 10:53
kaynak kullanıcı

oy
3

Ben sınıflara Normal durumda "mühürlü" düşünün ve ben her zaman "mühürlü" anahtar sözcüğü atlamak için bir neden var.

Benim için en önemli nedenleri şunlardır:

a) Daha iyi derleme sırasında tespit edilecek uygulanmadı arayüzleri için döküm (zaman kontrolleri derlemek, sadece çalışma zamanında)

ve üst nedeni:

b) benim sınıfların Kötüye bu şekilde mümkün değildir

Microsoft yapılmış standart, "mühürsüz" değil "mühürlü" isterdim.

Cevap 03/08/2010 saat 15:27
kaynak kullanıcı

oy
3

<Konu dışı-rant>

I nefret mühürlü sınıfları. Performans faydaları (ki sanmıyorum) şaşırtıcı olsa bile, bunlar tahrip miras yoluyla yeniden kullanımını önleyerek nesne yönelimli bir model. Örneğin, Konu sınıfı mühürlenir. Bir konu mümkün olduğunca verimli olmasını isteyebilirsiniz görmek mümkün olmakla birlikte, ben de büyük faydalar olurdu Konu alt sınıfı edememek senaryolar hayal edebiliyorum. Eğer varsa Sınıf yazarları gerekir "performans" nedenlerle sınıfları mühür, bir arayüz verin yüzden biz unuttuğunuz bir özellik gerektiğini her yerde değiştir sarın-ve-gerek yok en azından.

Örnek: SafeThread Konu mühürlü ve hiçbir IThread arayüzü yoktur çünkü Konu sınıfını sarmak zorunda; SafeThread otomatik parçacığı üzerinde işlenmemiş özel durumlar, tamamen Konu sınıfından eksik bir şey hapseder. [ve hayır, işlenmeyen özel durum olayları yapmak değil ikincil konuda işlenmemiş özel durumlar almak].

</ Konu dışı-rant>

Cevap 14/10/2008 saat 21:04
kaynak kullanıcı

oy
3

Sızdırmaz sınıfları gereken bir performans artışı sağlamaktadır. Kapalı bir sınıf elde edilemez olduğundan, herhangi bir sanal üye sanal olmayan üye dönüştürülebilir.

Tabii ki, biz gerçekten küçük kazançlar söz ediyoruz. profilleme bir sorun olarak indirdik sürece sadece performans artışı elde etmek mühürlü gibi bir sınıf işaretlemek olmaz.

Cevap 05/08/2008 saat 13:37
kaynak kullanıcı

oy
2

mühürlü sınıfları en az bir nebze daha hızlı olacaktır, ama bazen JIT Doktoru mantıklı oldum sanal aramaları olurdu aramaları satır içine alabilirsiniz eğer ... waayyy hızlı olabilir. satır içine yerleştirilmiş kadar küçük olan yöntemler sık ​​sık denilen olduğu yerde yani, kesinlikle sınıf sızdırmazlık düşünün.

Ancak sınıf mühür iyi neden bu miras edilecek tasarım vermedi" demek ki, bu yüzden bu kadar olacak şekilde tasarlanmıştır varsayarak yandı izin vermeyeceğim, ben gitmiyorum Ben ondan türetmek izin çünkü bir uygulama mahkum alma kendimi yakmak için."

Bazı burada onlar şeyden türetmek için fırsat istiyorum, çünkü onlar mühürlü sınıfları nefret ... ama bu GENELLİKLE en sürdürülebilir seçim değildir ... bir sınıf açığa bir çok kilitleri size türetme çünkü daha tüm maruz bırakmakla daha söylediler biliyorum söyledi. diyerek Onun benzer "Ben özel üye sınıfları nefret ... Ben sık sık sınıf I erişimi yok çünkü ben ne istersem onu ​​yapamazsınız." Kapsülleme önemli ... sızdırmazlık kapsülleme şekillerinden biridir.

Cevap 01/10/2011 saat 11:37
kaynak kullanıcı

oy
2

@Vaibhav, testlerin ne tür performansını ölçmek için çalıştırmak mı?

Bir kullanması gerekir sanırım Rotor ve CLI delemeyiz ve mühürlü bir sınıf performansını artıracak anlamak.

SSCLI (Rotor)
SSCLI: Paylaşılan Kaynak Ortak Dil Altyapı

Ortak Dil Altyapısı (CLI) .NET Framework çekirdek anlatılmaktadır ECMA standarttır. Ayrıca Rotor olarak bilinen Paylaşılan Kaynak CLI (SSCLI), ECMA CLI ve ECMA C # dili şartnamenin bir çalışma uygulanmasına kaynak kodun sıkıştırılmış arşiv olduğunu, Microsoft'un .NET mimarisinin merkezindedir teknolojiler.

Cevap 05/08/2008 saat 13:40
kaynak kullanıcı

oy
-9

Bu kodu çalıştırın ve mühürlü sınıfları 2 kat daha hızlı olduğunu görürsünüz:

class Program
{
    static void Main(string[] args)
    {
        Console.ReadLine();

        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 10000000; i++)
        {
            new SealedClass().GetName();
        }
        watch.Stop();
        Console.WriteLine("Sealed class : {0}", watch.Elapsed.ToString());

        watch.Start();
        for (int i = 0; i < 10000000; i++)
        {
            new NonSealedClass().GetName();
        }
        watch.Stop();
        Console.WriteLine("NonSealed class : {0}", watch.Elapsed.ToString());

        Console.ReadKey();
    }
}

sealed class SealedClass
{
    public string GetName()
    {
        return "SealedClass";
    }
}

class NonSealedClass
{
    public string GetName()
    {
        return "NonSealedClass";
    }
}

çıkış: Mühürlü sınıfı: 00: 00: 00,1897568 kapatılmamış sınıfı: 00: 00: 00,3826678

Cevap 26/11/2009 saat 18:50
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more