2009-05-27 19 views
18

किसी कारण से, मैंने हमेशा यह माना है कि readonly फ़ील्ड्स उनके साथ जुड़े हुए हैं, जिसे मैंने सीएलआर के रूप में सोचा था कि readonly फ़ील्ड प्रारंभ किया गया है या नहीं। यहां का ओवरहेड राज्य का ट्रैक रखने के लिए कुछ अतिरिक्त मेमोरी उपयोग होगा और मूल्य निर्दिष्ट करते समय चेक होगा।क्या कोई रन-टाइम ओवरहेड पढ़ने के लिए है?

शायद मुझे यह माना गया क्योंकि मुझे नहीं पता था कि readonly फ़ील्ड केवल एक कन्स्ट्रक्टर के अंदर या फील्ड घोषणा के भीतर ही शुरू किया जा सकता है और रन-टाइम चेक के बिना, आप यह गारंटी नहीं दे पाएंगे कि इसे असाइन नहीं किया जा रहा है विभिन्न तरीकों से कई बार। लेकिन अब मुझे यह पता है, इसे आसानी से सी # कंपाइलर द्वारा स्थिर रूप से चेक किया जा सकता है, है ना? तो क्या यह मामला है?

एक अन्य कारण यह है कि मैंने पढ़ा है कि readonly के उपयोग में 'मामूली' प्रदर्शन प्रभाव है, लेकिन वे इस दावे में कभी नहीं गए और मुझे इस विषय पर जानकारी नहीं मिल रही है, इसलिए मेरा प्रश्न। मुझे नहीं पता कि रन-टाइम चेक से अलग प्रदर्शन प्रदर्शन क्या हो सकता है।

एक तीसरा कारण मैंने देखा कि कि readonlyinitonly के रूप में संकलित आईएल में संरक्षित है है, इसलिए के लिए इस जानकारी आईएल में होना है, तो readonly कि क्षेत्र सी # संकलक द्वारा एक गारंटी से ज्यादा कुछ नहीं है क्या कारण है कभी कन्स्ट्रक्टर या घोषणा के बाहर असाइन नहीं किया जाता है?

दूसरी तरफ, मुझे पता चला है कि आप readonly int के मूल्य को सीएलआर के बिना अपवाद फेंकने के प्रतिबिंब के माध्यम से प्रतिबिंबित कर सकते हैं, जो संभव नहीं होना चाहिए यदि readonly रन-टाइम चेक था।

तो मेरा अनुमान है: 'रीडोनलिनेस' केवल एक संकलित समय सुविधा है, क्या कोई इसे पुष्टि/अस्वीकार कर सकता है? और यदि ऐसा है, तो आईएल में इस जानकारी को शामिल करने का क्या कारण है?

उत्तर

16

आपको इसे एक्सेस मॉडिफायर्स के समान दृष्टिकोण से देखना होगा। आईएल में एक्सेस संशोधक मौजूद हैं, लेकिन क्या वे वास्तव में रन-टाइम चेक हैं? (1) मैं सीधे संकलित समय पर निजी फ़ील्ड असाइन नहीं कर सकता, (2) मैं प्रतिबिंब का उपयोग करके उन्हें असाइन कर सकता हूं। अब तक ऐसा कोई रन-टाइम चेक नहीं लगता है, जैसे रीडोनली

लेकिन आइए एक्सेस मॉडिफायर्स की जांच करें।

  1. सार्वजनिक क्लास सी
  2. साथ विधानसभा A.dll बनाएँ विधानसभा B.exe संदर्भ A.dll बनाएँ: निम्न कार्य करें। बीएक्सई कक्षा सी
  3. दो असेंबली का निर्माण करता है। बीएक्सई चलाना ठीक काम करता है।
  4. A.dll को पुनर्निर्माण करें लेकिन कक्षा सी को आंतरिक में सेट करें। B.exe की निर्देशिका में A.dll को बदलें।

अब चल रहा है। बीएक्सई रनटाइम अपवाद फेंकता है।

एक्सेस संशोधक आईएल में भी मौजूद हैं, है ना? तो उनका उद्देश्य क्या है? इसका उद्देश्य यह है कि अन्य असेंबली जो .NET असेंबली को संदर्भित करती हैं उन्हें यह जानने की आवश्यकता होती है कि उन्हें किस तक पहुंचने की अनुमति है और उन्हें संकलन-समय और रन-टाइम दोनों तक पहुंचने की अनुमति नहीं है।

आईएल में एक समान उद्देश्य लगता है। यह अन्य असेंबली को बताता है कि क्या वे किसी विशेष प्रकार के क्षेत्र में लिख सकते हैं। हालांकि, readonly प्रतीत नहीं होता है कि उसी रन-टाइम जांच के लिए जो ऊपर दिए गए नमूने में संशोधक का उपयोग करता है।ऐसा लगता है कि केवल एक संकलन-समय की जांच है और रन-टाइम में नहीं होती है। प्रदर्शन के नमूने पर एक नज़र डालें: Read-only performance vs const

फिर, यह मतलब नहीं है कि आईएल बेकार है। आईएल सुनिश्चित करता है कि पहली बार एक संकलन-समय त्रुटि होती है। याद रखें, जब आप निर्माण करते हैं तो आप कोड के खिलाफ निर्माण नहीं करते हैं, लेकिन असेंबली।

+0

हूप्स, आपको वही प्रदर्शन विश्लेषण मिला जो मैंने किया था। तो आपको +1 करें और मैंने अपना (कम विस्तृत) उत्तर हटा दिया है। – Eddie

+0

सही समझ में आता है, धन्यवाद :) – JulianR

6

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

आप एक स्थिर केवल पढ़ने के लिए सदस्य का उपयोग कर रहे हैं, तो चीज़ें थोड़ी अलग ...

के बाद से स्थिर केवल पढ़ने के सदस्य स्थिर निर्माता के दौरान सेट है, JIT "जानता" है कि एक मूल्य मौजूद हैं। कोई अतिरिक्त मेमोरी नहीं है - केवल पढ़ने के लिए अन्य तरीकों को रोकता है, लेकिन यह संकलन समय की जांच है।

के बाद से JIT इस सदस्य कभी नहीं बदल सकते हैं जानता है, यह हो जाता है "हार्ड-कोडेड" रनटाइम पर, इसलिए अंतिम प्रभाव सिर्फ एक स्थिरांक मूल्य होने की तरह है। अंतर यह है कि इसमें जेआईटी समय के दौरान अधिक समय लगेगा, क्योंकि जेआईटी कंपाइलर को पढ़ने के मूल्य को हार्ड-वायर करने के लिए अतिरिक्त काम करने की आवश्यकता है। (हालांकि यह बहुत तेज़ होने जा रहा है।)

Expert C++/CLI मार्कस हेजी द्वारा इसका एक उचित अच्छा स्पष्टीकरण है।

3

यहां तक ​​कि अगर केवल पढ़ने के लिए केवल संकलन समय पर प्रभाव नहीं पड़ा, यह अभी भी विधानसभा में डाटा स्टोर करने के लिए आवश्यक हो सकता है (अर्थात आईएल)। CLR एक आमभाषा क्रम है - एक भाषा में लिखा कक्षाएं दोनों का इस्तेमाल किया और अन्य भाषाओं से बढ़ाया जा सकता है।

चूंकि सीएलआर के लिए प्रत्येक कंपाइलर को readonly फ़ील्ड के अर्थशास्त्र को संरक्षित करने के लिए, अन्य सभी भाषाओं को पढ़ने और संकलित करने के बारे में नहीं पता है, इसलिए उस डेटा को असेंबली में संग्रहीत करने की आवश्यकता है ताकि अन्य भाषाओं के लिए कंपेलर इसका सम्मान करेंगे।

बेशक, क्षेत्र को चिह्नित किया गया है readonly का अर्थ है कि जेआईटी ऑप्टिमाइज़ेशन (जैसे मूल्य के इनलाइन उपयोग) इत्यादि जैसी अन्य चीजें कर सकता है। इस तथ्य के बावजूद कि आपने क्षेत्र के मूल्य को बदलने के लिए प्रतिबिंब का उपयोग किया है, आईएल बनाना जो संबंधित कन्स्ट्रक्टर (उदाहरण या स्थिर, फ़ील्ड प्रकार के आधार पर) के बाहर initonly फ़ील्ड को संशोधित करता है, परिणामस्वरूप एक अविश्वसनीय असेंबली होगी।

4

एक महत्वपूर्ण बिंदु में अभी तक कोई अन्य उत्तर से उल्लेख नहीं किया है कि जब एक केवल पढ़ने के लिए क्षेत्र से पहुंचा जाता है, या जब किसी भी संपत्ति एक्सेस किया जाता है, अनुरोध डेटा की एक प्रतिलिपि का उपयोग कर संतुष्ट हो जाता है है। यदि प्रश्न में डेटा डेटा के 4-8 बाइट से अधिक मूल्य प्रकार है, तो इस अतिरिक्त प्रतिलिपि की लागत कभी-कभी महत्वपूर्ण हो सकती है। ध्यान दें कि जब वहाँ लागत में एक बड़ा कूद है जब structs 17 करने के लिए 16 बाइट्स से बड़े होते हैं, structs काफ़ी बड़ा हो सकता है और अभी भी तेजी से वर्गों की तुलना में, अगर वे भी अक्सर कॉपी नहीं कर रहे हैं कई अनुप्रयोगों में हो सकता है। उदाहरण के लिए, यदि किसी को ऐसा प्रकार माना जाता है जो त्रि-आयामी अंतरिक्ष में त्रिकोण के शिखर का प्रतिनिधित्व करता है। एक सरल कार्यान्वयन तीन float प्रत्येक बिंदु के लिए के साथ एक struct युक्त एक struct हो सकता है; शायद 36 बाइट कुल। यदि अंक, और प्रत्येक बिंदु के भीतर निर्देशांक, परिवर्तनीय सार्वजनिक फ़ील्ड हैं, तो कोई भी someTriangle.P1.X को त्वरित और आसानी से एक्सेस कर सकता है, बिना किसी डेटा को प्रतिलिपि 1 के समन्वय को छोड़कर। किसी भी समय, P1 एक संपत्ति या एक था readonly क्षेत्र, संकलक एक अस्थायी संरचना करने के लिए P1 कॉपी करने के लिए होगा, और फिर उस से X पढ़ें।

+0

यह एक बहुत पुराना सवाल हो सकता है, लेकिन यदि भविष्य में पाठक रुचि रखते हैं, तो जॉन स्कीट द्वारा निम्नलिखित ब्लॉग प्रविष्टि में इस उत्तर से संबंधित अधिक विस्तृत जानकारी शामिल है: http: //codeblog.jonskeet .uk/2014/07/16/माइक्रो-ऑप्टिमाइज़ेशन-आश्चर्यजनक-अक्षमता-पढ़ने-पढ़ने-फ़ील्ड/ –

+0

@ क्लिटोसकिर्यैक: मुझे नहीं लगता कि मैंने पहले उस विशेष पोस्ट को देखा होगा। मैं वास्तव में चाहता हूं कि .NET ने एक माध्यम प्रदान किया था जिसके द्वारा संरचना विधियां 'यह' लिखने का वादा नहीं कर सकती थीं या स्पष्ट रूप से कहती हैं कि वे ऐसा करते हैं, क्योंकि इससे संभवतः (1) कई तरीकों से प्रदर्शन में सुधार करना संभव होगा जो उन तरीकों को कॉल करते हैं जो कॉल नहीं करते हैं 'यह' लिखें [जैसा कि ब्लॉग में उल्लेख किया गया है], और (2) किसी को सुरक्षित रूप से उन तरीकों से सुरक्षित करने की अनुमति दें जो 'यह' लिखते हैं और संकलक को गैर-चर पर उन्हें आमंत्रित करने का प्रयास अस्वीकार कर देता है। ऐसे कई मामले हैं जहां सबसे तार्किक डेटा प्रकार अर्थात् एक परिवर्तनीय संरचना होगा, क्योंकि ... – supercat

+0

... पैटर्न 'structVar = structVar.withSomeChange();' थ्रेड-सुरक्षित नहीं बनाया जा सकता है, लेकिन 'structVar। makeSomeChange() 'कर सकते हैं [' Interlocked.CompareExchange'] का उपयोग कर। दुर्भाग्यवश, यदि कोई वर्ग [hypothetical] संरचना प्रकार 'AtomicBitVector32' की संपत्ति का खुलासा करता है, तो एक कंपाइलर चुपचाप' thing.flags.TestAndSetBit (23) जैसे ऑपरेशन के लिए फर्जी कोड उत्पन्न करेगा; 'अगर' फ्लैग 'एक संपत्ति है खेत। – supercat

संबंधित मुद्दे