C # में कोशिश / पकड़ का असली ओवरहेड क्या है?


94

इसलिए, मुझे पता है कि कोशिश / कैच कुछ ओवरहेड को जोड़ता है और इसलिए प्रक्रिया प्रवाह को नियंत्रित करने का एक अच्छा तरीका नहीं है, लेकिन यह ओवरहेड कहां से आता है और यह वास्तविक प्रभाव क्या है?

जवाबों:


52

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

मुझे नहीं लगता कि यह एक समस्या है जब तक आप अपवाद व्यवहार के लिए अपवाद का उपयोग कर रहे हैं (इसलिए कार्यक्रम के माध्यम से आपके विशिष्ट, अपेक्षित पथ नहीं)।


33
अधिक सटीक: कोशिश सस्ती है, पकड़ सस्ती है, फेंकना महंगा है। यदि आप कोशिश करने और पकड़ने से बचते हैं, तो फेंकना अभी भी महंगा है।
विंडोज प्रोग्रामर

4
हम्म - मार्क-अप टिप्पणियों में काम नहीं करता है। फिर से प्रयास करने के लिए - अपवाद त्रुटियों के लिए हैं, "असाधारण व्यवहार" या शर्तों के लिए नहीं: blogs.msdn.com/kcwalina/archive/2008/07/17/…
HTTP 410

2
@ विंडोज प्रोग्रामर आँकड़े / स्रोत कृपया?
कपे

100

यहां बनाने के लिए तीन बिंदु:

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

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

  • मेरा मानना ​​है कि यह एक कारण है कि सामान्य सलाह यदि आप throw;अपवाद को फिर से खत्म करने जा रहे हैं तो केवल अपवाद को फिर से फेंकने या एक नया निर्माण करें क्योंकि उन मामलों में सभी स्टैक जानकारी को फिर से व्यवस्थित किया जाता है जबकि सरल में फेंक यह सब संरक्षित है।


41
इसके अलावा: जब आप एक अपवाद को "थ्रो एक्स" के रूप में फिर से देखते हैं, तो आप मूल स्टैक ट्रेस खो देते हैं और इसे क्यूरेंट स्टैक ट्रेस से बदल देते हैं; शायद ही कभी चाहिए। यदि आप बस "फेंक" करते हैं, तो अपवाद में मूल स्टैक ट्रेस संरक्षित है।
एडी

@Eddie याthrow new Exception("Wrapping layer’s error", ex);
binki

21

क्या आप कोशिश कर रहे हैं कि ओवर / कैच / ओवरऑल के उपयोग के बारे में पूछ रहे हैं, जब अपवाद नहीं फेंके गए हैं, या प्रक्रिया प्रवाह को नियंत्रित करने के लिए अपवाद का उपयोग करने का ओवरहेड है? उत्तरार्द्ध कुछ हद तक एक बच्चा के जन्मदिन की मोमबत्ती को रोशन करने के लिए डायनामाइट की एक छड़ी का उपयोग करने के लिए समान है, और संबंधित ओवरहेड निम्नलिखित क्षेत्रों में आता है:

  • आप फेंकने वाले अपवाद के कारण अतिरिक्त कैश मिस की उम्मीद कर सकते हैं, जो सामान्य रूप से कैश में निवासी डेटा तक नहीं पहुंच सकता है।
  • गैर-निवासी कोड और डेटा को सामान्य रूप से आपके एप्लिकेशन के काम करने वाले सेट में नहीं पहुंचने के कारण आप अतिरिक्त पृष्ठ दोषों की अपेक्षा कर सकते हैं।

    • उदाहरण के लिए, अपवाद को फेंकने के लिए सीएलआर को अंतिम आईपी के स्थान का पता लगाने और वर्तमान आईपी और हर फ्रेम के रिटर्न आईपी को पकड़ने की आवश्यकता होगी, जब तक कि अपवाद को संभाला नहीं जाता है और फ़िल्टर ब्लॉक।
    • नैदानिक ​​उद्देश्यों के लिए फ्रेम बनाने के लिए अतिरिक्त निर्माण लागत और नाम समाधान, जिसमें मेटाडेटा आदि पढ़ना शामिल है।
    • उपरोक्त दोनों आइटम आम तौर पर "कोल्ड" कोड और डेटा तक पहुंचते हैं, इसलिए यदि आपके पास स्मृति दबाव है, तो कठिन पृष्ठ दोष संभावित हैं:

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

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


6

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

bool HasRight(string rightName, DomainObject obj) {
  try {
    CheckRight(rightName, obj);
    return true;
  }
  catch (Exception ex) {
    return false;
  }
}

void CheckRight(string rightName, DomainObject obj) {
  if (!_user.Rights.Contains(rightName))
    throw new Exception();
}

जब परीक्षण डेटा के साथ परीक्षण डेटाबेस फुलर हो गया, तो यह नए रूपों आदि को खोलते हुए बहुत ही धीमी गति से आगे बढ़ता है।

इसलिए मैंने इसे निम्नलिखित में बदल दिया, जो - बाद में त्वरित 'एन गंदे मापों के अनुसार - तीव्रता के 2 क्रमों के बारे में तेज़ी से है:

bool HasRight(string rightName, DomainObject obj) {
  return _user.Rights.Contains(rightName);
}

void CheckRight(string rightName, DomainObject obj) {
  if (!HasRight(rightName, obj))
    throw new Exception();
}

इसलिए संक्षेप में, सामान्य प्रक्रिया प्रवाह में अपवादों का उपयोग करना परिमाण के दो क्रमों के बारे में है, फिर अपवादों के बिना समान प्रक्रिया प्रवाह का उपयोग करना।


1
आप यहां अपवाद क्यों फेंकना चाहेंगे? आप मौके पर अधिकार नहीं होने के मामले को संभाल सकते थे।
थंडरग्राफ

@ThunderGr कि वास्तव में मैं क्या बदल गया है, यह परिमाण के दो आदेश तेजी से बना रही है।
तोबी

5

आम तौर पर स्वीकृत सिद्धांतों के विपरीत, try/ catchमहत्वपूर्ण प्रदर्शन निहितार्थ हो सकते हैं, और यह है कि एक अपवाद फेंक दिया गया है या नहीं!

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

पिछले कुछ वर्षों में Microsoft MVP द्वारा ब्लॉग पोस्ट के एक जोड़े में कवर किया गया है, और मुझे विश्वास है कि आप उन्हें आसानी से पा सकते हैं अभी तक StackOverflow सामग्री के बारे में बहुत परवाह करता है इसलिए मैं उनमें से कुछ को भराव सबूत के रूप में लिंक प्रदान करूंगा :

  • trycatchfinallyपीटर रिची द्वारा / / ( और भाग दो ) के प्रदर्शन निहितार्थ , उन आशाओं की पड़ताल करते हैं, जोtry/catch/finallyअक्षम करते हैं (और मैं मानक से उद्धरण के साथ इसमें आगे जाऊंगा)
  • परफॉर्मिंग प्रोफाइलिंग Parseबनाम TryParseबनामConvertTo इयान हफ द्वारा स्पष्ट रूप से कहा गया है कि "अपवाद हैंडलिंग बहुत धीमी है" और इस बिंदुको एक दूसरे के खिलाफथपथपाकरInt.Parseऔरप्रदर्शितकरता हैInt.TryParse... जो भी व्यक्तिपर्दे के पीछे/TryParseउपयोग करने काआग्रहकरता है, उसे कुछ प्रकाश डालना चाहिए!trycatch

यह उत्तर भी है जो असंतुष्ट कोड के बीच अंतर को दिखाता है- और बिना उपयोग किए try/ catch

यह बहुत स्पष्ट लगता है कि है एक ओवरहेड जो कोड पीढ़ी में तो एकदम मानने योग्य है, और कहा कि भूमि के ऊपर भी जो माइक्रोसॉफ्ट मूल्य लोगों द्वारा स्वीकार किया जा रहा है! फिर भी मैं इंटरनेट को दोहरा रहा हूं ...

हां, कोड की एक तुच्छ रेखा के लिए दर्जनों अतिरिक्त MSIL निर्देश हैं, और यह अक्षम अनुकूलन को भी कवर नहीं करता है, इसलिए तकनीकी रूप से यह एक माइक्रो-ऑप्टिमाइज़ेशन है।


मैंने एक उत्तर वर्ष पहले पोस्ट किया था जो प्रोग्रामर (मैक्रो-ऑप्टिमाइज़ेशन) की उत्पादकता पर केंद्रित होने के कारण हटा दिया गया था।

यह दुर्भाग्यपूर्ण है क्योंकि यहां कुछ नैनोसेकंडों की बचत नहीं हुई है और सीपीयू का समय मनुष्यों द्वारा मैनुअल अनुकूलन के कई संचित घंटों के लिए बनाए जाने की संभावना है। आपका बॉस किसके लिए अधिक भुगतान करता है: आपके समय का एक घंटा, या कंप्यूटर चलाने के साथ एक घंटा? किस बिंदु पर हम प्लग खींचते हैं और स्वीकार करते हैं कि यह सिर्फ एक तेज कंप्यूटर खरीदने का समय है ?

स्पष्ट रूप से, हमें अपनी प्राथमिकताओं का अनुकूलन करना चाहिए , न कि केवल हमारे कोड का! अपने अंतिम उत्तर में मैंने कोड के दो स्निपेट के बीच के अंतरों को आकर्षित किया।

का उपयोग कर try/ catch:

int x;
try {
    x = int.Parse("1234");
}
catch {
    return;
}
// some more code here...

उपयोग नहीं try/ catch:

int x;
if (int.TryParse("1234", out x) == false) {
    return;
}
// some more code here

एक रखरखाव डेवलपर के दृष्टिकोण से विचार करें, जो आपके समय को बर्बाद करने की अधिक संभावना है, अगर प्रोफाइलिंग / ऑप्टिमाइज़ेशन में नहीं (ऊपर कवर किया गया है), जो संभवतः भी आवश्यक नहीं होगा यदि यह try/ catchसमस्या के लिए नहीं था , तो स्क्रॉलिंग के माध्यम से स्रोत कोड ... उनमें से एक में बॉयलरप्लेट कचरा की चार अतिरिक्त लाइनें हैं!

जैसा कि अधिक से अधिक क्षेत्रों को एक वर्ग में पेश किया जाता है, यह सभी बॉयलरप्लेट कचरा जमा करता है (दोनों स्रोत और असंतुष्ट कोड में) उचित स्तर से परे। प्रति फ़ील्ड चार अतिरिक्त लाइनें, और वे हमेशा एक ही रेखाएँ होती हैं ... क्या हमें खुद को दोहराने से बचने के लिए नहीं सिखाया गया था? मुझे लगता है कि हम कुछ होम-ब्रूअड एब्सट्रैक्ट के पीछे try/ छिप सकते हैं catch, लेकिन ... फिर हम अपवादों (यानी उपयोग Int.TryParse) से बच सकते हैं ।

यह एक जटिल उदाहरण भी नहीं है; मैंने try/ में नई कक्षाओं को तुरंत शुरू करने के प्रयास देखे हैं catch। इस बात पर विचार करें कि कंस्ट्रक्टर के अंदर सभी कोड को तब कुछ अनुकूलन से अयोग्य ठहराया जा सकता है जो अन्यथा संकलक द्वारा स्वचालित रूप से लागू किया जाएगा। इस सिद्धांत को जन्म देने के लिए बेहतर तरीका क्या है कि कंपाइलर धीमा है , क्योंकि कंपाइलर का विरोध ठीक उसी तरह हो रहा है जैसा कि उसे बताया जाता है ?

उक्त कंस्ट्रक्टर द्वारा एक अपवाद मान लिया गया है, और कुछ बग को ट्रिगर किया गया है, जिसके परिणामस्वरूप खराब रखरखाव डेवलपर को फिर इसे ट्रैक करना होगा। यह इतना आसान काम नहीं हो सकता है, क्योंकि गोटो दुःस्वप्न के स्पेगेटी कोड के विपरीत , try/ तीन आयामोंcatch में गड़बड़ी पैदा कर सकता है , क्योंकि यह स्टैक को न केवल एक ही विधि के अन्य भागों में स्थानांतरित कर सकता है, बल्कि अन्य कक्षाएं और विधियां भी हो सकती हैं। , जो सभी रखरखाव डेवलपर, कठिन तरीके से देखा जाएगा ! फिर भी हमें बताया गया है कि "गोटो खतरनाक है", हे!

अंत में मैं उल्लेख करता हूं, try/ catchइसका लाभ है जो है, इसे अनुकूलन को अक्षम करने के लिए डिज़ाइन किया गया है ! यह है, अगर आप करेंगे, एक डिबगिंग सहायता ! यही कारण है कि यह के लिए डिजाइन किया गया था और यह है कि यह के रूप में इस्तेमाल किया जाना चाहिए ...

मुझे लगता है कि यह एक सकारात्मक बिंदु भी है। इसका उपयोग उन आशाओं को अक्षम करने के लिए किया जा सकता है जो अन्यथा सुरक्षित, बहुस्तरीय अनुप्रयोगों के लिए सुरक्षित मैसेज पासिंग एल्गोरिदम, और संभावित दौड़ की स्थिति को पकड़ने के लिए;) हो सकता है कि केवल एक ही परिदृश्य के बारे में मैं कोशिश / पकड़ का उपयोग करने के बारे में सोच सकता हूं। यहां तक ​​कि इसके विकल्प भी हैं।


क्या अनुकूलन करते हैं try, catchऔर finallyअक्षम करते हैं?

उर्फ

कैसे हैं try, catchऔर finallyएड्स डिबगिंग के रूप में उपयोगी?

वे लिखते हैं-बाधाएँ। यह मानक से आता है:

12.3.3.13 ट्राइ-कैच स्टेटमेंट्स

एक बयान के लिए stmt फार्म की:

try try-block
catch ( ... ) catch-block-1
... 
catch ( ... ) catch-block-n
  • के निश्चित काम राज्य वी की शुरुआत में कोशिश-ब्लॉक के निश्चित काम राज्य के रूप में ही है वी की शुरुआत में stmt
  • के निश्चित काम राज्य वी की शुरुआत में पकड़-ब्लॉक-मैं (किसी के लिए मैं ) के निश्चित काम राज्य के रूप में ही है वी की शुरुआत में stmt
  • Stmt के अंतिम-बिंदु पर v की निश्चित असाइनमेंट स्थिति निश्चित रूप से असाइन की गई है (और केवल अगर) v को निश्चित रूप से ट्राइ -ब्लॉक और प्रत्येक कैच-ब्लॉक-आई के अंत-बिंदु पर सौंपा गया है (प्रत्येक i से n के लिए) )।

दूसरे शब्दों में, प्रत्येक tryकथन की शुरुआत में :

  • tryबयान दर्ज करने से पहले दृश्यमान वस्तुओं के लिए किए गए सभी असाइनमेंट पूरे होने चाहिए, जिसमें एक शुरुआत के लिए थ्रेड लॉक की आवश्यकता होती है, जिससे यह डीबगिंग की स्थिति के लिए उपयोगी होता है!
  • संकलक को इसकी अनुमति नहीं है:
    • अप्रयुक्त चर असाइनमेंट को समाप्त करें जो निश्चित रूप से tryबयान से पहले असाइन किए गए हैं
    • इसके किसी भी आंतरिक कार्य को पुनर्गठित करें या इसके साथ तालमेल बिठाएँ (अर्थात यदि आपने पहले से ऐसा नहीं किया है तो मेरी पहली कड़ी देखें)।
    • इस बाधा पर लहराते असाइनमेंट, एक चर को असाइनमेंट में देरी करने के लिए जो यह जानता है कि बाद में (यदि सभी पर) तक उपयोग नहीं किया जाएगा या पूर्व-खाली करने के लिए बाद में असाइनमेंट को आगे बढ़ाना होगा ताकि अन्य अनुकूलन संभव हो सकें ...

प्रत्येक catchकथन के लिए एक समान कहानी होती है ; मान लें कि आपके tryकथन के भीतर (या एक रचनाकार या यह कार्य करता है, आदि) आप उस अन्यथा निरर्थक चर (यह कहते हैं garbage=42;) को असाइन करते हैं, संकलक उस कथन को समाप्त नहीं कर सकता है, भले ही यह कार्यक्रम के अचूक व्यवहार के लिए कितना भी अप्रासंगिक हो। । ब्लॉक में प्रवेश करने से पहले असाइनमेंट पूरा करना होगा catch

जो इसके लायक है, finallyवह इसी तरह की अपमानजनक कहानी बताता है :

12.3.3.14 कोशिश-अंत में बयान

एक के लिए कोशिश बयान stmt फार्म की:

try try-block
finally finally-block

• के निश्चित काम राज्य वी की शुरुआत में कोशिश-ब्लॉक के निश्चित काम राज्य के रूप में ही है वी की शुरुआत में stmt
• के निश्चित काम राज्य वी की शुरुआत में अंत में ब्लॉक के निश्चित काम राज्य के रूप में ही है वी की शुरुआत में stmt
stmt के अंतिम बिंदु पर v की निश्चित असाइनमेंट स्थिति निश्चित रूप से (और केवल यदि) या तो असाइन की गई है : o v निश्चित रूप से try-block o v के अंतिम बिंदु पर असाइन की गई हैनिश्चित रूप से अंत-ब्लॉक के अंत बिंदु पर सौंपा गया है यदि एक नियंत्रण प्रवाह हस्तांतरण (जैसे कि एक गोटो बयान) बनाया जाता है, जो कि कोशिश-ब्लॉक के भीतर शुरू होता है , और कोशिश-ब्लॉक के बाहर समाप्त होता है , तो v को भी निश्चित रूप से उस पर सौंपा गया माना जाता है नियंत्रण प्रवाह अंतरण अगर v निश्चित रूप से अंत-ब्लॉक के अंतिम बिंदु पर सौंपा गया है । (यह केवल एक ही नहीं है - यदि v निश्चित रूप से इस नियंत्रण प्रवाह हस्तांतरण पर किसी अन्य कारण से असाइन किया गया है, तो यह अभी भी निश्चित रूप से असाइन किया गया है।)

12.3.3.15 ट्राइ-कैच-आखिर स्टेटमेंट्स

एक कोशिश के लिए निश्चित असाइनमेंट विश्लेषण - पकड़ - अंत में फार्म का बयान:

try try-block
catch ( ... ) catch-block-1
... 
catch ( ... ) catch-block-n
finally finally-block

किया जाता है के रूप में अगर बयान एक थे कोशिश - अंत में बयान एक enclosing कोशिश - पकड़ बयान:

try { 
    try   
    try-block
    catch ( ... ) catch-block-1
    ...   
    catch ( ... ) catch-block-n
} 
finally finally-block

3

यह उल्लेख करने के लिए नहीं कि क्या यह एक बार-बार विधि के अंदर है, यह अनुप्रयोग के समग्र व्यवहार को प्रभावित कर सकता है।
उदाहरण के लिए, मैं ज्यादातर मामलों में Int32.Parse के उपयोग को एक बुरा अभ्यास मानता हूं क्योंकि यह किसी ऐसी चीज के अपवाद को फेंकता है जिसे अन्यथा आसानी से पकड़ा जा सकता है।

इसलिए यहां लिखी गई हर चीज को समाप्त करने के लिए:
1) अप्रत्याशित त्रुटियों को पकड़ने के लिए try..catch ब्लॉकों का उपयोग करें - लगभग कोई प्रदर्शन जुर्माना नहीं।
2) यदि आप इसे से बच सकते हैं तो अपवादित त्रुटियों के अपवादों का उपयोग न करें।


3

मैंने थोड़ी देर पहले इस बारे में एक लेख लिखा था क्योंकि उस समय बहुत सारे लोग इस बारे में पूछ रहे थे। आप इसे और http://www.blackwasp.co.uk/SpeedTestTryCatch.aspx पर परीक्षण कोड पा सकते हैं ।

उतावलापन यह है कि एक कोशिश / कैच ब्लॉक के लिए ओवरहेड की एक छोटी मात्रा है लेकिन इतना छोटा है कि इसे अनदेखा किया जाना चाहिए। हालाँकि, यदि आप लाखों बार निष्पादित किए गए लूप में कोशिश / कैच ब्लॉक चला रहे हैं, तो आप संभव हो तो ब्लॉक को लूप के बाहर ले जाने पर विचार कर सकते हैं।

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


2

मैंने पिछले साल इस विषय के बारे में एक ब्लॉग प्रविष्टि की । इसकी जांच - पड़ताल करें। लब्बोलुआब यह है कि अगर कोई अपवाद नहीं होता है, तो एक कोशिश ब्लॉक के लिए लगभग कोई लागत नहीं है - और मेरे लैपटॉप पर, एक अपवाद लगभग 36μs था। यह आपकी अपेक्षा से कम हो सकता है, लेकिन ध्यान रखें कि वे परिणाम जहां उथले स्टैक पर हैं। इसके अलावा, पहले अपवाद वास्तव में धीमा हैं।


मैं आपके ब्लॉग तक नहीं पहुँच सका (कनेक्शन का समय समाप्त हो रहा है? क्या आप उपयोग कर रहे हैं try/ catchबहुत अधिक? हे हेह), लेकिन आप भाषा कल्पना और कुछ एमएस एमवीपी के साथ बहस कर रहे हैं जिन्होंने इस विषय पर ब्लॉग भी लिखा है, माप प्रदान करते हैं आपकी सलाह के विपरीत ... मैं सुझाव के लिए खुला हूं कि मैंने जो शोध किया है वह गलत है, लेकिन मुझे यह देखने के लिए आपके ब्लॉग प्रविष्टि को पढ़ने की आवश्यकता होगी।
ऑटिस्टिक

@ हफ़थोर के ब्लॉग पोस्ट के अलावा, यहां कोड के साथ एक और ब्लॉग पोस्ट है जो विशेष रूप से गति प्रदर्शन अंतरों को परखने के लिए लिखा गया है। परिणामों के अनुसार, यदि आपके पास अपवाद केवल 5% समय भी होता है, तो अपवाद हैंडलिंग कोड गैर-अपवाद हैंडलिंग कोड की तुलना में कुल मिलाकर 100x धीमा है। आलेख विशेष रूप से try-catchब्लॉक बनाम tryparse()विधियों को लक्षित करता है , लेकिन अवधारणा समान है।

2

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

मेरे लिए, प्रोग्रामर और गुणवत्ता ओवरहेड प्रक्रिया प्रवाह के लिए ट्राइ-कैच का उपयोग करने के खिलाफ प्राथमिक तर्क है।

अपवादों का कंप्यूटर ओवरहेड तुलना में नगण्य है, और आमतौर पर वास्तविक-विश्व प्रदर्शन आवश्यकताओं को पूरा करने के लिए आवेदन की क्षमता के मामले में छोटा है।


@ रिटचर्ड टी, क्यों? प्रोग्रामर और गुणवत्ता उपरि की तुलना में यह नगण्य है।
थंडरग्राफ

1

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

मैं कहूंगा कि कोशिश करने में संकोच न करें..जब भी आवश्यक हो और इसे बुद्धिमानी से उपयोग करें!

उदाहरण के लिए, यह विधि वर्कफ़्लो में भाग लेती है ...

टिप्पणियाँ?

public bool DeleteGallery(int id)
{
    try
    {
        using (var transaction = new DbTransactionManager())
        {
            try
            {
                transaction.BeginTransaction();

                _galleryRepository.DeleteGallery(id, transaction);
                _galleryRepository.DeletePictures(id, transaction);

                FileManager.DeleteAll(id);

                transaction.Commit();
            }
            catch (DataAccessException ex)
            {
                Logger.Log(ex);
                transaction.Rollback();                        
                throw new BusinessObjectException("Cannot delete gallery. Ensure business rules and try again.", ex);
            }
        }
    }
    catch (DbTransactionException ex)
    {
        Logger.Log(ex);
        throw new BusinessObjectException("Cannot delete gallery.", ex);
    }
    return true;
}

2
डेविड, क्या आप कॉल को एक कोशिश / कैच ब्लॉक में 'DeleteGallery' पर लपेटेंगे?
रॉब

चूंकि DeleteGallery एक बूलियन फ़ंक्शन है, इसलिए मुझे लगता है कि अपवाद को वहां फेंकना उपयोगी नहीं है। इसके लिए डिलीटगैलरी में कॉल को एक कोशिश / कैच ब्लॉक में संलग्न करना होगा। अगर ((डिलीटगैलरी (सहायता)) {// हैंडल} मेरे लिए अधिक सार्थक है। उस विशिष्ट उदाहरण में।
थंडरगार्ड

1

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

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

मेरी अंग्रेजी के बारे में क्षमा करें, आशा है कि यह आपकी मदद करती है। यह जानकारी उद्धृत पुस्तक पर आधारित है, अधिक जानकारी के लिए अध्याय 8.5 अपवाद हैंडलिंग से संबंधित है।


संकलक रनटाइम पर चित्र से बाहर है। वहाँ गया है ताकि CLR अपवाद संभाल कर सकते हैं ट्राई / कैच ब्लॉकों के लिए एक ओवरहेड हो। .NET CLR (एक वर्चुअल मशीन) पर C # चलता है। यह मुझे लगता है कि ब्लॉक का ओवरहेड खुद ही न्यूनतम है जब कोई अपवाद नहीं है लेकिन अपवाद को संभालने वाले सीएलआर की लागत बहुत महत्वपूर्ण है।
थंडरग्राफ

-4

जब उपयोग किया जाना चाहिए, जहां उपयोग नहीं किया जाना चाहिए, तब हमें एक कोशिश / कैच ब्लॉक की सबसे बड़ी संभावित लागतों में से एक का विश्लेषण करें:

int x;
try {
    x = int.Parse("1234");
}
catch {
    return;
}
// some more code here...

और यहाँ एक कोशिश के बिना / पकड़ है:

int x;
if (int.TryParse("1234", out x) == false) {
    return;
}
// some more code here

महत्वहीन श्वेत-अंतरिक्ष की गिनती नहीं, कोई यह देख सकता है कि कोड के ये दो समान टुकड़े बाइट्स में लगभग समान लंबाई के हैं। उत्तरार्द्ध में 4 बाइट्स कम इंडेंटेशन शामिल हैं। क्या यह गलत बात है?

चोट के अपमान को जोड़ने के लिए, एक छात्र लूप का फैसला करता है जबकि इनपुट को इंट के रूप में पार्स किया जा सकता है। बिना कोशिश / पकड़ने के समाधान कुछ इस तरह हो सकता है:

while (int.TryParse(...))
{
    ...
}

लेकिन कोशिश / कैच का उपयोग करते समय यह कैसा दिखता है?

try {
    for (;;)
    {
        x = int.Parse(...);
        ...
    }
}
catch
{
    ...
}

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

छोटी लागतों में से एक यह है कि कोशिश / कैच ब्लॉक वास्तव में कुछ अनुकूलन को अक्षम करते हैं: http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implication-of-try-catch-finally.aspx । मुझे लगता है कि यह एक सकारात्मक बिंदु भी है। इसका उपयोग उन आशाओं को निष्क्रिय करने के लिए किया जा सकता है जो अन्यथा सुरक्षित, बहुस्तरीय अनुप्रयोगों के लिए सुरक्षित मैसेज पासिंग एल्गोरिदम, और संभावित दौड़ की स्थिति को पकड़ने के लिए हो सकता है;) यह एकमात्र परिदृश्य है जिसके बारे में मैं कोशिश / पकड़ का उपयोग करने के बारे में सोच सकता हूं। यहां तक ​​कि इसके विकल्प भी हैं।


1
मुझे पूरा यकीन है कि TryParse एक कोशिश करता है {int x = int.Parse ("xxx"); सच्चा लौटें;} पकड़ें {असत्य लौटें; } आंतरिक रूप से। इंडेंटेशन सवाल में कोई चिंता नहीं है, केवल प्रदर्शन और ओवरहेड है।
थंडरगार्ड

@ThunderGr वैकल्पिक रूप से, मेरे द्वारा पोस्ट किया गया नया उत्तर पढ़ें । इसमें अधिक लिंक शामिल हैं, जिनमें से एक बड़े पैमाने पर प्रदर्शन को बढ़ावा देने का विश्लेषण है जब आप Int.Parseइसके पक्ष में बचते हैं Int.TryParse
ऑटिस्टिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.