अपवाद फेंकने के लिए प्रदर्शन विचार

मैं कई बार निम्नलिखित प्रकार के कोड में आया हूं, और मुझे आश्चर्य है कि यह एक अच्छा अभ्यास है (प्रदर्शन परिप्रेक्ष्य से) या नहीं:

try
{
    ... // some code
}
catch (Exception ex)
{
    ... // Do something
    throw new CustomException(ex);
}

असल में, कोडर क्या कर रहा है यह है कि वे एक अपवाद को अपवाद में शामिल कर रहे हैं और इसे फिर से फेंक रहे हैं।

निम्नलिखित दो से प्रदर्शन में यह अलग कैसे है:

try
{
    ... // some code
}
catch (Exception ex)
{
    .. // Do something
    throw ex;
}

या

try
{
    ... // some code
}
catch (Exception ex)
{
    .. // Do something
    throw;
}

Putting aside any functional याcoding best practice arguments, is there any performance difference between the 3 approaches?

0
ro fr bn

8 उत्तर

@ ब्रैड टटरो

पहले मामले में अपवाद खो नहीं जा रहा है, इसे कन्स्ट्रक्टर में पास किया जा रहा है। हालांकि मैं बाकी के साथ आपसे सहमत हूं, दूसरा दृष्टिकोण स्टैक ट्रेस के नुकसान की वजह से एक बहुत बुरा विचार है। जब मैंने .NET के साथ काम किया, तो मैंने कई मामलों में भाग लिया जहां अन्य प्रोग्रामर ने ऐसा किया, और जब मुझे अपवाद के सही कारण को देखने की ज़रूरत होती, तो मुझे किसी भी अंत तक निराशा होती है, केवल इसे एक विशाल प्रयास ब्लॉक से पुनर्स्थापित करने के लिए अब मुझे पता नहीं है कि समस्या कहां उत्पन्न हुई थी।

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

हमेशा मेट्रिक्स होने पर प्रदर्शन को अनुकूलित करें जो आपको इंगित करता है कि आपको प्रदर्शन को अनुकूलित करने की आवश्यकता है, और फिर उन स्पॉट्स को दबाएं जो अपराधी साबित हुए हैं।

आसान डिबगिंग क्षमताओं के साथ पठनीय कोड होना बेहतर है (आईई स्टैण्ड ट्रेस छुपा नहीं रहा है) कुछ नैनोसेकंद को तेजी से चलाने के बजाए।

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

0
जोड़ा

डेविड की तरह, मुझे लगता है कि दूसरा और तीसरा बेहतर प्रदर्शन करता है। लेकिन क्या तीनों में से कोई भी इस बारे में चिंतित होने के लिए पर्याप्त रूप से खर्च करने के लिए पर्याप्त प्रदर्शन करेगा? मुझे लगता है कि प्रदर्शन के बारे में चिंता करने की तुलना में बड़ी समस्याएं हैं।

FxCop हमेशा दूसरे पर तीसरे दृष्टिकोण की सिफारिश करता है ताकि मूल स्टैक ट्रेस खो न जाए।

संपादित करें: हटाई गई सामग्री जो कि केवल सादा गलत थी और माइक इंगित करने के लिए काफी दयालु था।

0
जोड़ा

आपके पहले उदाहरण में फेंकने के लिए एक नई CustomException ऑब्जेक्ट के निर्माण का उपर है।

आपके दूसरे उदाहरण में फिर से फेंकने के प्रकार अपवाद का अपवाद फेंक देगा।

आपके तीसरे उदाहरण में फिर से फेंकने से आपके "कुछ कोड" द्वारा फेंक दिए गए उसी प्रकार का अपवाद फेंक देगा।

तो दूसरे और तीसरे उदाहरण कम संसाधनों का उपयोग करते हैं।

0
जोड़ा

जाहिर है आप नई ऑब्जेक्ट्स (नई अपवाद) बनाने के दंड में आते हैं, ठीक उसी तरह जैसे आप अपने प्रोग्राम में शामिल कोड की प्रत्येक पंक्ति के साथ करते हैं, आपको यह तय करना होगा कि अपवादों का बेहतर वर्गीकरण अतिरिक्त काम के लिए भुगतान करता है या नहीं।

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

हालांकि, अन्य परिस्थितियों में, अपवादों का पदानुक्रम होने से आपके वर्ग के उपयोगकर्ता के लिए बहुत सुविधाजनक है। मान लीजिए कि आप फेकाडे पैटर्न को कार्यान्वित कर रहे हैं न तो अब तक के विचारों के अच्छे हैं:

  1. यह अच्छा नहीं है कि आप प्रत्येक अपवाद को अपवाद वस्तु के रूप में उठाएं क्योंकि आप (संभवतः) मूल्यवान जानकारी खो रहे हैं
  2. अच्छा नहीं है न तो आपके द्वारा पकड़े गए हर प्रकार की वस्तु को बढ़ाने के लिए क्योंकि ऐसा करने से आप मुखौटा बनाने में विफल रहे हैं

इस कल्पित मामले में, बेहतर बात यह है कि अपवाद वर्गों का पदानुक्रम बनाना है, जो आपके उपयोगकर्ताओं को सिस्टम की आंतरिक जटिलताओं से जोड़ते हैं, उन्हें उत्पादित अपवाद के बारे में कुछ जानने की अनुमति देता है।

अलग नोट के रूप में:

मैं व्यक्तिगत रूप से तर्क लागू करने के लिए अपवादों (अपवाद वर्ग से प्राप्त कक्षाओं के पदानुक्रम) के उपयोग से नापसंद करता हूं। मामले की तरह:

try {
        // something that will raise an exception almost half the time
} catch( InsufficientFunds e) {
        // Inform the customer is broke
} catch( UnknownAccount e ) {
        // Ask for a new account number
}
0
जोड़ा

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

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

0
जोड़ा

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

यदि मैं कोड में कुछ निर्भरताओं को रद्द करना चाहता हूं तो मैं व्यक्तिगत रूप से कस्टम अपवादों का उपयोग करता हूं। उदाहरण के लिए, मेरे पास एक विधि है जो किसी xml फ़ाइल से डेटा लोड करती है। यह कई अलग-अलग तरीकों से गलत हो सकता है।

यह डिस्क (FileIOException) से पढ़ने में विफल हो सकता है, उपयोगकर्ता इसे कहीं से एक्सेस करने का प्रयास कर सकता है जहां उन्हें अनुमति नहीं है (सुरक्षा अपवाद), फ़ाइल दूषित हो सकती है (XmlParseException), डेटा गलत प्रारूप (DeserialisationException) में हो सकता है।

इस मामले में, इसलिए कॉलिंग क्लास के लिए यह सब कुछ समझना आसान है, इन सभी अपवादों में एक कस्टम अपवाद (FileOperationException) को फिर से शुरू किया गया है, जिसका अर्थ है कि कॉलर को System.IO या System.Xml के संदर्भों की आवश्यकता नहीं है, लेकिन फिर भी एक enum और किसी भी महत्वपूर्ण जानकारी के माध्यम से क्या त्रुटि हुई।

जैसा कि कहा गया है, इस तरह कुछ माइक्रो-ऑप्टिमाइज़ करने का प्रयास न करें, अपवाद फेंकने का कार्य सबसे धीमा चीज है जो यहां होता है। एक अपवाद से बचने का प्रयास करना सबसे अच्छा सुधार है।

public bool Load(string filepath)
{
  if (File.Exists(filepath)) //Avoid throwing by checking state
  {
    //Wrap anyways in case something changes between check and operation
    try { .... }
    catch (IOException ioFault) { .... }
    catch (OtherException otherFault) { .... }
    return true; //Inform caller of success
  }
  else { return false; } //Inform caller of failure due to state
}
0
जोड़ा

मत करो:

try
{
    // some code
}
catch (Exception ex) { throw ex; }

चूंकि यह स्टैक ट्रेस खो देगा।

इसके बजाए:

try
{
    // some code
}
catch (Exception ex) { throw; }

बस फेंक देगा, आपको केवल अपवाद चर को पारित करने की आवश्यकता है यदि आप चाहते हैं कि यह एक नए कस्टम अपवाद पर आंतरिक अपवाद हो।

0
जोड़ा
अच्छा बिंदु - मुझे कॉपी-पेस्ट में याद आया।
जोड़ा लेखक Keith, स्रोत
छोटे जोड़ - पूर्व को हटाएं अन्यथा आप अप्रयुक्त चर चेतावनी बनाते हैं। {// कुछ कोड} पकड़ने (अपवाद) {फेंकने का प्रयास करें; }
जोड़ा लेखक Dennis, स्रोत

रुको .... अगर अपवाद फेंक दिया जाता है तो हम प्रदर्शन के बारे में क्यों परवाह करते हैं? जब तक हम सामान्य अनुप्रयोग प्रवाह के हिस्से के रूप में अपवादों का उपयोग नहीं कर रहे हैं (जो सर्वोत्तम अभ्यास के खिलाफ है)।

मैंने सफलता के संबंध में केवल प्रदर्शन आवश्यकताओं को देखा है लेकिन विफलता के संबंध में कभी नहीं।

0
जोड़ा