सील वर्गों वास्तव में प्रदर्शन लाभ प्रदान करते हैं?

वोट
118

मैं जो कहना है कि आप अपनी कक्षाओं के रूप में अतिरिक्त प्रदर्शन लाभ पाने के लिए सील कर दिया निशान चाहिए अनुकूलन युक्तियों की एक बहुत भर में आ गए हैं।

मैं प्रदर्शन अंतर जाँच करने के लिए कुछ परीक्षण भाग गया और कोई भी नहीं मिला। क्या मुझसे कुछ गलत हो रही है? मैं इस मामले में जहां सील कक्षाएं बेहतर परिणाम मिलेगा, याद आ रही है?

किसी को भी परीक्षण चलाने के लिए और एक अंतर देखा गया है?

मुझे जानने मदद :)

05/08/2008 को 13:00
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


11 जवाब

वोट
133

जवाब है नहीं, सील वर्गों की तुलना में गैर सील बेहतर प्रदर्शन नहीं करते।

मुद्दे से नीचे आता है callबनाम callvirtआईएल सेशन कोड। Callकी तुलना में तेजी है callvirt, और callvirtमुख्य रूप से जब आप अगर वस्तु subclassed कर दिया गया है पता नहीं है प्रयोग किया जाता है। ताकि लोगों को लगता है कि अगर आप एक वर्ग सील सभी सेशन कोड से बदल जाएगा calvirtsकरने के लिए callsऔर तेजी से हो जाएगा।

दुर्भाग्य से callvirtअन्य चीजें हैं जो इसे उपयोगी भी कर, अशक्त संदर्भ के लिए जाँच की तरह करता है। इसका मतलब यह है कि भले ही एक वर्ग बंद है, संदर्भ अभी भी अशक्त हो सकता है और इस तरह एक callvirtकी जरूरत है। आप (वर्ग सील करने के लिए जरूरत के बिना) इस के आसपास मिल सकती है, लेकिन यह थोड़ा व्यर्थ हो जाता है।

Structs का उपयोग callक्योंकि वे subclassed नहीं किया जा सकता और अशक्त कभी नहीं कर रहे हैं।

अधिक जानकारी के लिए इस सवाल का देखें:

कॉल और callvirt

24/12/2008 को 03:09
का स्रोत उपयोगकर्ता

वोट
46

घबराना कभी कभी सील कक्षाओं में तरीकों के गैर आभासी कॉल का उपयोग करेगा के बाद से वहाँ कोई रास्ता नहीं है वे आगे बढ़ाया जा सकता है।

वहाँ बुला प्रकार के बारे में जटिल नियम, आभासी / nonvirtual कर रहे हैं, और मैं उन्हें नहीं जानता कि सब तो मैं वास्तव में आप के लिए उन्हें रूपरेखा नहीं कर सकते हैं, लेकिन अगर आप सील वर्गों और आभासी तरीकों के लिए गूगल आप विषय पर कुछ लेख मिल सकती है।

ध्यान दें कि प्रदर्शन लाभ के किसी भी प्रकार आप अनुकूलन के इस स्तर से प्राप्त करेगा अंतिम उपाय के रूप में माना जाना चाहिए, हमेशा एल्गोरिथम स्तर पर अनुकूलन इससे पहले कि आप कोड-स्तर पर अनुकूलन।

: यहाँ एक लिंक इस उल्लेख है सील कीवर्ड पर पर्यटन

05/08/2008 को 13:32
का स्रोत उपयोगकर्ता

वोट
20

मुझे पता है, वहाँ प्रदर्शन लाभ की कोई गारंटी नहीं है। लेकिन वहाँ है कुछ विशेष शर्त के तहत प्रदर्शन की सजा कम करने के लिए एक मौका सील विधि के साथ। (सील वर्ग सभी तरीकों को सील किया गया है।)

लेकिन यह संकलक कार्यान्वयन और निष्पादन वातावरण पर निर्भर है।


विवरण

आधुनिक CPUs से कई लंबे पाइपलाइन संरचना का उपयोग प्रदर्शन को बढ़ाने के लिए। क्योंकि सीपीयू स्मृति से अविश्वसनीय रूप से तेजी से होता है, सीपीयू पाइपलाइन में तेजी लाने के स्मृति से कोड prefetch गया है। कोड उचित समय पर तैयार नहीं है, तो पाइपलाइनों बेकार हो जाएगा।

वहाँ एक बड़ी बाधा कहा जाता है गतिशील प्रेषण जो इस 'प्रीफेचिंग' अनुकूलन बाधित। तुम सिर्फ एक सशर्त शाखाओं के रूप में इस बात को समझ सकते हैं।

// 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();

सीपीयू इस मामले में निष्पादित करने के लिए अगले कोड prefetch नहीं कर सकते हैं अगले कोड स्थिति अज्ञात है क्योंकि जब तक हालत हल हो गई है। तो यह बनाता है खतरा पाइपलाइन निष्क्रिय कारण बनता है। और निष्क्रिय द्वारा प्रदर्शन दंड नियमित में बहुत बड़ा है।

इसी बात विधि अधिभावी के मामले में होता है। संकलक वर्तमान विधि कॉल के लिए उचित विधि अधिभावी निर्धारित कर सकते हैं, लेकिन कभी कभी यह असंभव है। इस मामले में, उचित विधि केवल रनटाइम पर निर्धारित किया जा सकता। यह भी गतिशील प्रेषण का एक मामला है, और तो डायनामिक रूप से टाइप किया भाषाओं की एक मुख्य कारण यह है कि आम तौर पर स्थिर टाइप भाषाओं की तुलना में धीमी है।

कुछ सीपीयू (हाल ही में इंटेल के 86 चिप्स सहित) कहा जाता है तकनीक का उपयोग करता सट्टा निष्पादन भी स्थिति पर पाइप लाइन का उपयोग करने के। बस निष्पादन पथ में से एक prefetch। लेकिन इस तकनीक का मारा दर इतनी अधिक नहीं है। और अटकलें विफलता पाइपलाइन स्टाल जो भी विशाल प्रदर्शन दंड बनाता कारण बनता है। (इस सीपीयू कार्यान्वयन से पूरी तरह से है। कुछ मोबाइल सीपीयू के रूप में ऊर्जा बचाने के लिए अनुकूलन के इस प्रकार नहीं है जाना जाता है)

असल में, सी # एक स्थिर संकलित भाषा है। लेकिन हमेशा नहीं। मैं सही हालत पता नहीं है और यह पूरी तरह संकलक कार्यान्वयन पर निर्भर है। कुछ compilers विधि अधिभावी को रोकने यदि विधि के रूप में चिह्नित किया गया है द्वारा गतिशील प्रेषण की संभावना को दूर कर सकते हैं sealed। बेवकूफ compilers नहीं हो सकता। इस के प्रदर्शन लाभ है sealed


इस उत्तर ( क्यों यह तेजी से एक अवर्गीकृत सरणी की तुलना में एक हल कर देता है पर कार्रवाई करने के? है शाखा भविष्यवाणी एक बहुत बेहतर वर्णन है)।

03/02/2011 को 16:22
का स्रोत उपयोगकर्ता

वोट
18

अद्यतन: .NET कोर 2.0 और .NET डेस्कटॉप 4.7.1 के रूप में, CLR अब devirtualization का समर्थन करता है। यह सील कक्षाओं में तरीकों ले जा सकते हैं और सीधे कॉल के साथ आभासी कॉल की जगह - और यह भी अगर यह पता लगा सकते हैं कि ऐसा करना सुरक्षित है गैर सील कक्षाओं के लिए ऐसा कर सकते हैं।

इस तरह के एक मामले में (एक सील बंद वर्ग कि CLR अन्यथा के रूप में सुरक्षित नहीं पता लगा सकता है devirtualise करने के लिए) में, एक सील बंद वर्ग वास्तव में प्रदर्शन लाभ के कुछ प्रकार की पेशकश करनी चाहिए।

जिसके अनुसार, मुझे लगता है कि नहीं होगा इसके बारे में चिंता के लायक हो जाएगा , जब तक कि आप पहले से ही कोड प्रोफाइल था और निर्धारित किया है कि आप एक विशेष रूप से गर्म रास्ते में थे या ऐसा ही कुछ लाखों बार, बुलाया जा रहा है:

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


मूल उत्तर:

मैं निम्नलिखित परीक्षण कार्यक्रम बनाया है, और फिर देखने के लिए क्या MSIL कोड उत्सर्जित किया गया था परावर्तक का उपयोग कर इसे decompiled।

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");
}

सभी मामलों में, सी # संकलक (रिलीज़ निर्माण विन्यास में दृश्य स्टूडियो 2010) का उत्सर्जन करता है समान MSIL है, जो इस प्रकार है:

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 

बार-बार उद्धृत कारण यह है कि लोगों को सील कहना प्रदर्शन लाभ प्रदान करता है संकलक जानता है कि वर्ग ओवरराइड नहीं कर रहा है, और इस प्रकार का उपयोग कर सकते है callके बजाय callvirtके रूप में यह जैसा कि ऊपर साबित virtuals, आदि के लिए जाँच करने के लिए नहीं है, यह नहीं है सच।

मेरा अगला सोचा कि भले ही MSIL समान है, शायद JIT कम्पाइलर व्यवहार करता है अलग ढंग से सील कक्षाएं था?

मैं विजुअल स्टूडियो डीबगर के तहत एक रिलीज निर्माण भाग गया और decompiled 86 उत्पादन देखी। दोनों ही मामलों में 86 कोड समान था, वर्ग के नाम और समारोह स्मृति पते (जो निश्चित रूप से अलग होना चाहिए) के अपवाद के साथ। यह रहा

//            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 

मैं तो शायद डिबगर के तहत चल रहा सोचा का कारण बनता है यह कम आक्रामक अनुकूलन प्रदर्शन करने के लिए?

मैं तो एक स्टैंडअलोन रिहाई किसी भी डिबगिंग वातावरण के निष्पादन के बाहर का निर्माण भाग गया, और बाद कार्यक्रम पूरा किया था में तोड़ने, और JIT संकलित 86 कोड की dissasembly देखने पर WinDBG + एसओएस का इस्तेमाल किया।

आप नीचे दिए गए कोड से देख सकते हैं, जब डिबगर के बाहर चल रहा है JIT कम्पाइलर और अधिक आक्रामक है, और यह inlined है WriteItसीधे फोन करने वाले में विधि। महत्वपूर्ण बात यह है कि हालांकि यह है कि यह जब बुला एक बनाम गैर-सील वर्ग सील समान था है। वहाँ एक सील या nonsealed वर्ग के बीच कोई अंतर नहीं है।

यहाँ यह तब होता है जब एक सामान्य वर्ग बुला:

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

एक सील बंद वर्ग बनाम:

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

मेरे लिए, यह ठोस सबूत है कि वहाँ प्रदान करता है नहीं कर सकते बनाम गैर-सील वर्गों सील ... मुझे लगता है कि मैं अब खुश हूँ पर तरीकों बुला के बीच किसी भी प्रदर्शन में सुधार हो सकता है :-)

20/02/2012 को 21:45
का स्रोत उपयोगकर्ता

वोट
4

एक वर्ग के अंकन sealedकोई प्रदर्शन असर होना चाहिए।

ऐसे मामले हैं cscएक फेंकना करना पड़ सकता है callvirtएक के बजाय opcode callopcode। हालांकि, ऐसा लगता है उन मामलों दुर्लभ हैं।

और मुझे लगता है कि JIT के लिए एक ही गैर आभासी समारोह कॉल फेंकना में सक्षम होना चाहिए callvirtइसके लिए होगा कि call, यह जानता है कि किसी भी वर्ग उपवर्गों नहीं है (अभी तक) है। विधि का केवल एक कार्यान्वयन मौजूद है, तो वहाँ से एक vtable-बस सीधे एक कार्यान्वयन फोन इसका पता लोड हो रहा है कोई मतलब नहीं है। उस बात के लिए, JIT भी समारोह इनलाइन कर सकते हैं।

यह JIT की ओर से एक जुआ का एक सा है, क्योंकि अगर एक उपवर्ग है बाद में भरी हुई, JIT दूर है कि मशीन कोड फेंक और कोड फिर से संकलन, एक असली आभासी कॉल उत्सर्जक करना होगा। मेरा अनुमान है यह कि व्यवहार में ऐसा नहीं होता है।

(और हाँ, वीएम डिजाइनरों वास्तव में आक्रामक तरीके से इन छोटे प्रदर्शन जीत का पीछा करते हैं।)

20/11/2009 को 10:53
का स्रोत उपयोगकर्ता

वोट
3

मैं "सील" पर विचार करें कक्षाएं सामान्य मामले और मैं हमेशा "सील" कीवर्ड को छोड़ करने के लिए एक कारण है।

मेरे लिए सबसे महत्वपूर्ण कारण हैं:

एक) बेहतर समय चेक (संकलन लागू नहीं किया संकलन समय पर पता लगाया जाएगा इंटरफेस के कास्टिंग, न केवल रनटाइम पर)

और, शीर्ष कारण:

ख) मेरी कक्षाओं का दुरुपयोग संभव नहीं है कि जिस तरह से

काश माइक्रोसॉफ्ट बना दिया है "सील" होगा मानक, "सील न की गयी" नहीं।

03/08/2010 को 15:27
का स्रोत उपयोगकर्ता

वोट
3

<विषय से हटकर शेख़ी>

मैं घृणा सील कक्षाएं। यहां तक कि अगर प्रदर्शन लाभ अद्भुत (जो मुझे शक है) हैं, वे नष्ट विरासत के माध्यम से पुन: उपयोग रोकने के द्वारा वस्तु उन्मुख मॉडल। उदाहरण के लिए, थ्रेड वर्ग बंद है। मैं देख सकता हूँ है कि एक धागे संभव के रूप में कुशल होने के लिए चाहते हो सकता है, मैं भी जहां थ्रेड उपवर्ग के लिए महान लाभ के लिए होता है में सक्षम होने के परिदृश्यों की कल्पना कर सकते हैं। कक्षा लेखकों, यदि आप चाहिए "प्रदर्शन" कारणों के लिए अपनी कक्षाओं सील, एक इंटरफेस प्रदान कृपया कम से कम तो हम लपेट और बदलने के लिए हर जगह है कि हम एक ऐसी सुविधा है आप भूल गए की जरूरत नहीं है।

उदाहरण: SafeThread क्योंकि थ्रेड बंद है और वहाँ कोई IThread इंटरफेस है थ्रेड वर्ग रैप करने के लिए था, SafeThread स्वचालित रूप से धागे पर बिना क्रिया अपवाद हैं, कुछ पूरी तरह से धागा वर्ग से लापता फंसा लेती है। [और कोई, बिना क्रिया का अपवाद घटनाओं है नहीं अप माध्यमिक धागे में बिना क्रिया अपवाद लेने]।

</ विषय से हटकर शेख़ी>

14/10/2008 को 21:04
का स्रोत उपयोगकर्ता

वोट
3

मुहरबंद कक्षाएं चाहिए एक प्रदर्शन में सुधार प्रदान करते हैं। के बाद से एक सील बंद वर्ग प्राप्त नहीं किया जा सकता है, किसी भी आभासी सदस्यों गैर आभासी सदस्यों में तब्दील किया जा सकता है।

बेशक, हम वास्तव में छोटे लाभ बात कर रहे हैं। मैं एक वर्ग के रूप में बस, जब तक की रूपरेखा एक समस्या यह पता चला एक प्रदर्शन में सुधार लाने के लिए सील कर दिया निशान नहीं होगा।

05/08/2008 को 13:37
का स्रोत उपयोगकर्ता

वोट
2

सील कक्षाओं में कम से कम एक छोटा सा तेजी से हो जाएगा, लेकिन कभी कभी waayyy तेजी से हो सकता है ... अगर JIT अनुकूलक कॉल है कि अन्यथा किया गया आभासी कॉल करना होगा इनलाइन कर सकते हैं। तो, जहां वहाँ बार-बार कहा जाता है तरीकों कि बहुत छोटे से inlined हो रहे हैं, निश्चित रूप से वर्ग सील पर विचार करें।

हालांकि, एक वर्ग सील करने के लिए सबसे अच्छा कारण कहते हैं "मैं डिजाइन नहीं था इस से विरासत में मिला जा सकता है, तो मैं आप यह सोचते हैं कि ऐसा हो डिजाइन किया गया था द्वारा जला दिया हो जाने के लिए नहीं जा रहा हूँ, और मैं नहीं जा रहा हूँ अपने आप को एक कार्यान्वयन में बंद कर दिया हो रही है, क्योंकि मैं आप इसे से प्राप्त करते हैं द्वारा जलाने के लिए। "

मैं पता कुछ यहां कहा है कि वे सभी को उजागर नहीं की तुलना में अधिक सील कक्षाएं नफरत है क्योंकि वे कुछ भी से प्राप्त करने के अवसर चाहते हैं ... लेकिन है कि अक्सर सबसे पोषणीय विकल्प नहीं है ... एक बहुत में आप ताले व्युत्पत्ति क्योंकि एक वर्ग को उजागर उस। कह करने के लिए अपने समान "मैं वर्गों निजी सदस्यों है कि घृणा ... मैं अक्सर वर्ग जो मैं चाहता क्योंकि मैं पहुँच नहीं है ऐसा नहीं कर सकता।" Encapsulation महत्वपूर्ण है ... सीलिंग कैप्सूलीकरण में से एक रूप है।

01/10/2011 को 11:37
का स्रोत उपयोगकर्ता

वोट
2

@Vaibhav, परीक्षण आप किस तरह के प्रदर्शन को मापने के अमल किया?

मुझे लगता है कि एक का उपयोग करने के लिए होता रोटर और CLI और गहराई में जाने और समझ कैसे एक मोहरबंद वर्ग प्रदर्शन में सुधार होगा।

SSCLI (रोटर)
SSCLI: साझा स्रोत सामान्य भाषा इंफ्रास्ट्रक्चर

सामान्य भाषा इन्फ्रास्ट्रक्चर (CLI) ECMA मानक कि .नेट फ्रेमवर्क के मूल का वर्णन है। साझा स्रोत CLI (SSCLI), भी रोटर के रूप में जाना, ECMA CLI और ECMA सी # भाषा विनिर्देशन का एक काम कर रहे कार्यान्वयन के लिए स्रोत कोड की एक संकुचित संग्रह है, माइक्रोसॉफ्ट के नेट वास्तुकला के दिल में प्रौद्योगिकियों।

05/08/2008 को 13:40
का स्रोत उपयोगकर्ता

वोट
-9

इस कोड को चलाने के लिए और आपको लगता है कि सील कक्षाएं 2 गुना तेजी से कर रहे हैं देख सकते हैं:

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";
    }
}

उत्पादन: मुहरबंद वर्ग: 00: 00: ००.१८९७५६८ NonSealed वर्ग: 00: 00: ००.३८,२६,६७८

26/11/2009 को 18:50
का स्रोत उपयोगकर्ता

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