स्थिर तरीकों बनाम आवृत्ति विधियों का प्रदर्शन


108

मेरा प्रश्न स्थिर तरीकों बनाम उदाहरण विधियों और उनके स्केलेबिलिटी के प्रदर्शन विशेषताओं से संबंधित है। इस परिदृश्य के लिए मान लें कि सभी वर्ग परिभाषाएँ एक ही असेंबली में हैं और एकाधिक असतत पॉइंटर प्रकार की आवश्यकता है।

विचार करें:

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

उपरोक्त कक्षाएं एक सहायक शैली पैटर्न का प्रतिनिधित्व करती हैं।

एक उदाहरण वर्ग में, StaticClass का विरोध करने के लिए आवृत्ति विधि को हल करने में कुछ समय लगता है।

मेरे प्रश्न हैं:

  1. जब राज्य रखना कोई चिंता का विषय नहीं है (कोई फ़ील्ड या गुण आवश्यक नहीं हैं), तो क्या स्थैतिक वर्ग का उपयोग करना हमेशा बेहतर होता है?

  2. जहां इन स्थिर वर्ग परिभाषाओं की संख्या काफी अधिक है (उदाहरण के लिए 100 कहो, प्रत्येक स्थिर विधियों की संख्या के साथ) क्या यह निष्पादन प्रदर्शन या स्मृति खपत को प्रभावित करेगा उदाहरण संख्या परिभाषाओं की समान संख्या की तुलना में?

  3. जब एक ही उदाहरण वर्ग के भीतर एक अन्य विधि कहा जाता है, तो क्या उदाहरण का समाधान अभी भी होता है? उदाहरण के लिए एक ही उदाहरण के this.DoOperation2("abc")भीतर से [इस] कीवर्ड का उपयोग करना DoOperation1



"उदाहरण संकल्प" से आपका क्या अभिप्राय है? IL स्तर पर, "यह" पॉइंटर किसी अन्य स्थानीय वैरिएबल की तरह ही उपलब्ध है। वास्तव में, कुछ पुराने सीएलआर / जेआईटी संस्करणों पर, आप एक NULL पर एक इंस्टेंस-विधि कह सकते हैं, बशर्ते कि वह 'इस' को नहीं छूती है - कोड सिर्फ के माध्यम से भाग गया और कुछ भी नहीं पर क्रैश हो गया .. अब CLR / JIT में स्पष्ट अशक्त हैं- हर सदस्य की जाँच करें ..
quetzalcoatl

> vijaymukhi.com/documents/books/ilbook/chap8.htm और 'कॉल उदाहरण' बनाम 'कॉल'। पूर्व को उम्मीद है कि यह 'पैरामीटर' है और बाद वाला - doesn't।
quetzalcoatl 10

@Quetzalcoatl भ्रम के लिए खेद है, सवाल एक ही उदाहरण से विधि के लिए अधिक विधि थी और अगर उस उदाहरण को स्वयं हल करने की आवश्यकता होती है।
बर्नी व्हाइट

1
@quetzalcoatl मुझे लगता है कि वह इसका मतलब है, "क्या संकलक जाँच से छुटकारा पाता है कि thisजब कोई वर्ग अपने आप में एक इंस्टेंस विधि कहता है?"
जॉन हन्ना

जवाबों:


152

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

व्यवहार में, यह इतना कम अंतर बनाता है कि यह विभिन्न संकलक निर्णयों के शोर में छिपा होगा। (इसलिए दो लोग असहमत परिणामों के साथ दूसरे से बेहतर साबित कर सकते हैं)। कम से कम नहीं है क्योंकि thisआम तौर पर एक रजिस्टर में पारित किया जाता है और अक्सर उस रजिस्टर में होता है जिसके साथ शुरू करना है।

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

वास्तविक प्रदर्शन अंतर कम हो जाएगा कि क्या आपको कृत्रिम रूप से स्मृति में ऑब्जेक्ट मिला है कुछ ऐसा करने के लिए जो स्वाभाविक रूप से स्थिर होना चाहिए, या आप जटिल तरीके से ऑब्जेक्ट-पासिंग की जंजीरों को उलझा रहे हैं कि स्वाभाविक रूप से क्या होना चाहिए।

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

नंबर 2. कोई फर्क नहीं पड़ता। प्रत्येक सदस्य के लिए प्रति-वर्ग लागत की एक निश्चित राशि है, यह दोनों की शर्तें है कि कितना मेटाडेटा है, वास्तविक DLL या EXE फ़ाइल में कितना कोड है, और कितना jitted कोड होगा। यह वही है चाहे वह उदाहरण हो या स्थिर।

आइटम 3 के साथ, thisइस प्रकार thisहै। हालाँकि ध्यान दें:

  1. thisपैरामीटर एक विशेष रजिस्टर में पारित हो जाता है। एक ही क्लास के भीतर एक इंस्टेंस मेथड को कॉल करते समय, यह संभवतः पहले से ही उस रजिस्टर में होगा (जब तक कि उसे स्टेक नहीं किया गया था और किसी कारण से इस्तेमाल किया गया रजिस्टर), और इसलिए thisइसे सेट करने के लिए कोई भी कार्रवाई करने की आवश्यकता नहीं है। । यह एक निश्चित सीमा पर लागू होता है, उदाहरण के लिए पहले दो मापदंडों को विधि के पहले दो मापदंडों को बनाता है जो इसे बनाता है।

  2. चूंकि यह स्पष्ट होगा कि thisयह शून्य नहीं है, इसलिए इसका उपयोग कुछ मामलों में कॉल को अनुकूलित करने के लिए किया जा सकता है।

  3. चूंकि यह स्पष्ट होगा कि thisयह अशक्त नहीं है, इससे इनलाइन विधि कॉल फिर से अधिक कुशल हो सकती है, क्योंकि विधि कॉल को नकली करने के लिए निर्मित कोड कुछ नल-जांचों को छोड़ सकता है जो इसे वैसे भी आवश्यकता हो सकती है।

  4. उस ने कहा, शून्य जांच सस्ते हैं!

यह ध्यान देने योग्य है कि सामान्य स्थैतिक विधियाँ किसी वस्तु पर कार्य करती हैं, उदाहरण के तरीकों के बजाय, http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- पर चर्चा की गई कुछ लागतों को कम कर सकती हैं। संबंधित-ओवरहेड्स / उस मामले में जहां दिए गए स्थिर को किसी दिए गए प्रकार के लिए नहीं बुलाया जाता है। जैसा कि वह कहते हैं, "एक तरफ के रूप में, यह पता चला है कि विस्तार के तरीके जेनेरिक अमूर्त को अधिक भुगतान के लिए खेलने का एक शानदार तरीका है।"

हालांकि, ध्यान दें कि यह केवल विधि द्वारा उपयोग किए जाने वाले अन्य प्रकार के तात्कालिकता से संबंधित है, जो अन्यथा मौजूद नहीं है। जैसे, यह वास्तव में बहुत सारे मामलों पर लागू नहीं होता है (कुछ अन्य उदाहरण विधि उस प्रकार का उपयोग करते हैं, कुछ अन्य कोड कहीं और उस प्रकार का उपयोग करते हैं)।

सारांश:

  1. ज्यादातर उदाहरण बनाम स्टेटिक की प्रदर्शन लागत नगण्य से कम है।
  2. आम तौर पर जहां आप उदाहरण के लिए स्थैतिक का दुरुपयोग करते हैं या इसके विपरीत, वहां क्या लागतें आती हैं। यदि आप इसे स्थिर और उदाहरण के बीच अपने निर्णय का हिस्सा नहीं बनाते हैं, तो आपको सही परिणाम मिलने की अधिक संभावना है।
  3. ऐसे दुर्लभ मामले हैं, जिनमें अन्य प्रकारों में स्थिर जेनेरिक विधियों का निर्माण कम प्रकार से होता है, उदाहरण के तौर पर जेनेरिक विधियां, जो इसे कभी- कभी उपयोग किए जाने वाले छोटे लाभ के लिए बना सकती हैं (और "शायद ही कभी" संदर्भित करता है कि यह किस प्रकार के साथ प्रयोग किया जाता है। अनुप्रयोग का जीवनकाल, न जाने कितनी बार कहा जाता है)। एक बार जब आप उस लेख के बारे में बात कर रहे होते हैं, तो आप देखेंगे कि यह वैसे भी अधिकांश स्थैतिक-बनाम-निर्णय निर्णयों के लिए 100% अप्रासंगिक है। संपादित करें: और इसमें ज्यादातर लागत केवल ngen के साथ है, न कि jitted कोड के साथ।

संपादित करें: सिर्फ एक नोट कि कैसे सस्ते नल-चेक हैं (जो मैंने ऊपर दावा किया है)। .NET में अधिकांश null- चेक null के लिए जाँच नहीं करते हैं, बल्कि वे जारी रखते हैं कि वे इस धारणा के साथ क्या करने जा रहे थे कि यह काम करेगा, और यदि एक एक्सेस अपवाद होता है तो यह एक में बदल जाता है NullReferenceException। जैसे, ज्यादातर जब वैचारिक रूप से C # कोड में एक शून्य-जांच शामिल है क्योंकि यह एक उदाहरण सदस्य तक पहुंच रहा है, अगर यह सफल होता है तो लागत वास्तव में शून्य है। एक अपवाद कुछ इनबिल्ड कॉल होगा, (क्योंकि वे व्यवहार करना चाहते हैं जैसे कि उन्होंने एक उदाहरण सदस्य को बुलाया है) और उन्होंने एक ही व्यवहार को ट्रिगर करने के लिए एक फ़ील्ड मारा, इसलिए वे बहुत सस्ते भी हैं, और वे अभी भी अक्सर बाहर रह सकते हैं (उदाहरण के लिए अगर विधि में पहला कदम एक क्षेत्र तक पहुँचने के रूप में शामिल था)।


क्या आप इस बात पर टिप्पणी कर सकते हैं कि स्थिर बनाम उदाहरण प्रश्न का कैश सहारे पर कोई असर है? क्या कैश मिस होने की संभावना एक या दूसरे पर निर्भर है? क्या एक अच्छी रूपरेखा बता रही है कि क्यों?
18

@scriptocalypse वास्तव में नहीं। अनुदेश कैश में कोई अंतर नहीं दिखेगा, और उस स्तर पर डेटा thisको एक स्पष्ट पैरामीटर के माध्यम से या एक्सेस करने में बहुत अंतर नहीं है । यहां एक बड़ा प्रभाव यह होगा कि संबंधित डेटा (डेटा प्रकार के फ़ील्ड या सरणी मान संदर्भ प्रकार फ़ील्ड में डेटा की तुलना में अधिक नज़दीकी) और पहुंच के पैटर्न के कितने करीब हैं।
जॉन हन्ना

"सिद्धांत रूप में, हमें एक स्थिर विधि की अपेक्षा करनी चाहिए जो किसी वस्तु को एक पैरामीटर के रूप में लेती है और उसके साथ कुछ ऐसा करती है कि वह उसी वस्तु पर एक उदाहरण के रूप में समतुल्य से थोड़ा कम अच्छा हो।" - क्या आपका मतलब है कि यदि ऊपर नमूना विधि लेता है। स्ट्रिंग के बजाय ऑब्जेक्ट के रूप में पैरामीटर, गैर-स्थिर बेहतर है? उदाहरण के लिए: मेरे पास मेरी स्टैटिक विधि ऑब्जेक्ट को पैरामीटर के रूप में लेती है और इसे स्ट्रिंग और रिटर्न स्ट्रिंग में सीरियल करती है। क्या आप इस मामले में गैर-स्थैतिक का उपयोग करने का सुझाव दे रहे हैं?
१17

1
@batmaci मेरा मतलब है कि एक अच्छा मौका obj.DoSomehting(2)इससे थोड़ा सस्ता होगा DoSomething(obj, 2)लेकिन जैसा कि मैंने भी कहा कि अंतर इतना मामूली है और इतनी छोटी चीज़ों पर निर्भर है जो अंतिम संकलन में अलग हो सकता है कि यह वास्तव में चिंता करने लायक नहीं है। यदि आप किसी चीज को महंगे के रूप में कर रहे हैं (यहाँ खेलने में अंतर के सापेक्ष) एक स्ट्रिंग को कुछ करने के लिए तो यह विशेष रूप से व्यर्थ है।
जॉन हैना

इसमें एक, शायद स्पष्ट, महत्वपूर्ण बात है जो इस अन्यथा उत्कृष्ट उत्तर में गायब है: एक उदाहरण विधि के लिए एक उदाहरण की आवश्यकता होती है, और एक उदाहरण बनाना सस्ता नहीं होता है। यहां तक ​​कि एक डिफ़ॉल्ट को ctorअभी भी सभी क्षेत्रों के प्रारंभ की आवश्यकता है। एक बार जब आपके पास पहले से ही एक उदाहरण है, तो यह उत्तर लागू होता है ("अन्य सभी चीजें समान हो रही हैं")। बेशक, एक महंगा cctorस्थिर तरीकों को भी धीमा कर सकता है, लेकिन यह केवल पहली कॉल पर लागू होता है जो समान तरीकों से लागू होता है। Docs.microsoft.com/en-us/prepret-versions/dotnet/articles/…
Abel

8

जब राज्य रखना कोई चिंता का विषय नहीं है (कोई फ़ील्ड या गुण आवश्यक नहीं हैं), तो क्या स्थैतिक वर्ग का उपयोग करना हमेशा बेहतर होता है?

मैं हाँ कहूँगा। जैसा कि staticआप कुछ घोषित करते हैं, आप स्टेटलेस एक्जीक्यूशन का इरादा घोषित करते हैं (यह अनिवार्य नहीं है, लेकिन किसी चीज़ का इरादा अपेक्षित होगा)

जहाँ इन स्थिर वर्गों की संख्या (उदाहरण के लिए 100, प्रत्येक स्थिर विधियों की एक संख्या के साथ) है, क्या यह निष्पादन प्रदर्शन या स्मृति खपत को उसी तरह की संख्या वर्गों की तुलना में नकारात्मक रूप से प्रभावित करेगा?

ऐसा न सोचें, जब तक आपको यकीन न हो कि स्टैटिक क्लासेस वास्तव में बहुत ही बेकार हैं, इसका कारण यह है कि स्मृति आवंटन में आसानी से गड़बड़ न हो और मेमोरी लीक न हो।

जब [इसी] कीवर्ड का उपयोग उसी उदाहरण वर्ग के भीतर किसी अन्य विधि को कॉल करने के लिए किया जाता है, तो क्या उदाहरण रिज़ॉल्यूशन अभी भी होता है?

इस बिंदु के बारे में निश्चित नहीं है (यह सीएलआर का विशुद्ध रूप से कार्यान्वयन विवरण है), लेकिन हाँ सोचें।


स्टेटिक तरीकों का मजाक नहीं उड़ाया जा सकता, अगर आप टीडीडी या सिर्फ यूनिट टेस्टिंग करते हैं तो इससे आपके टेस्ट को काफी नुकसान पहुंचेगा।
ट्रैम्पस्टर

@trampster क्यों? यह सिर्फ तर्क का एक टुकड़ा है। आप आसानी से क्या आप इसे दे नकली कर सकते हैं? सही व्यवहार प्राप्त करने के लिए। और बहुत से स्टैटिक तरीके किसी भी तरह से एक फ़ंक्शन में निजी टुकड़े होंगे।
एम। मिम्पेन

@ M.Mimpen के रूप में लंबे समय के रूप में आप इसे छोटे निजी टुकड़ों के लिए छोड़ देते हैं अपने ठीक है, अगर एक सार्वजनिक विधि और आप इसे अन्य बंद से उपयोग करते हैं और इसे बदलने की आवश्यकता है कि यह आपके परीक्षण में क्या करता है तो आपकी अटक गई, फ़ाइल IO या डेटाबेस एक्सेस जैसी चीजें या नेटवर्क कॉल वगैरह, अगर स्टैटिक मेथड में डाल दिया जाए तो यह अनमोल हो जाएगा, जब तक कि आप यह नहीं कहेंगे कि आप स्थैतिक विधि के पैरामीटर के रूप में एक नकली निर्भरता को इंजेक्ट करते हैं
ट्रैम्पस्टर

-2

स्थिर विधियाँ तेज़ लेकिन कम OOP हैं, यदि आप डिज़ाइन पैटर्न का उपयोग करेंगे स्थैतिक विधि संभावना ख़राब कोड, स्टेटिक के बिना व्यापार तर्क को बेहतर लिखने के लिए, फ़ाइल पढ़ने जैसे सामान्य कार्य, WebRequest आदि को स्थैतिक के रूप में बेहतर एहसास ... आपके सवालों का कोई सार्वभौमिक नहीं है उत्तर


16
आपने अपने दावों पर कोई तर्क नहीं दिया।
यमजोरों

2
@ fjch1997 2 upvoters लगता है कि अन्यथा (इसके लायक क्या है) के लिए। डाउनवोट्स
ymajoros
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.