.NET (C #) अनुप्रयोगों के लिए प्रदर्शन अनुकूलन

छवि

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

1. ToArray vs ToList


public IEnumerable<string> GetItems() { return _storage.Items.Where(...).ToList(); } 

सहमत हूं, औद्योगिक परियोजनाओं के लिए एक बहुत ही विशिष्ट कोड। लेकिन उसका क्या कसूर है? IEnumerable इंटरफ़ेस एक संग्रह देता है जिसे आप "जा सकते हैं"; यह इंटरफ़ेस का अर्थ यह नहीं है कि हम तत्वों को जोड़ / निकाल सकते हैं। तदनुसार, लिन्क अभिव्यक्ति को सूची (टोलिस्ट) में डालकर समाप्त करने की आवश्यकता नहीं है। इस मामले में, ऐरे (ToArray) के लिए कास्टिंग बेहतर है। चूंकि सूची एरे पर एक आवरण है, और इस आवरण द्वारा प्रदान की गई सभी अतिरिक्त विशेषताएं, हम इंटरफ़ेस को काट देते हैं। एक सरणी कम मेमोरी का उपभोग करती है, और इसके मूल्यों तक पहुंच तेज होती है। तदनुसार, अधिक भुगतान क्यों करें। एक ओर, यह अनुकूलन महत्वपूर्ण नहीं है, क्योंकि वे कहते हैं कि "मैचों पर अनुकूलन", लेकिन यह पूरी तरह से सच नहीं है। तथ्य यह है कि एक विशिष्ट एप्लिकेशन में, जिसमें सेवाएं प्रस्तुति परत के लिए मॉडल लौटाती हैं, ऐसी टूलाइस्ट कॉल का एक असंख्य हो सकता है। ऊपर वर्णित उदाहरण में, IEnumerable इंटरफ़ेस केवल उदाहरण के लिए पेश किया गया है। यह दृष्टिकोण सभी मामलों के लिए प्रासंगिक है जब आपको एक संग्रह वापस करने की आवश्यकता होती है जिसे आप बाद में बदलने नहीं जा रहे हैं।

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

2. "फ़ाइल पथ" पैरामीटर हमेशा आपकी पद्धति के लिए सबसे अच्छा विकल्प नहीं है


एपीआई का विकास करते समय, विधि हस्ताक्षरों से बचें जो इनपुट के रूप में एक फ़ाइल पथ प्राप्त करते हैं (आपकी विधि द्वारा बाद में प्रसंस्करण के लिए)। इसके बजाय, इनपुट करने के लिए या अंतिम उपाय स्ट्रीम के रूप में बाइट्स के एक सरणी को पास करने की क्षमता प्रदान करें। तथ्य यह है कि समय के साथ, आपकी विधि न केवल डिस्क से एक फ़ाइल पर लागू की जा सकती है, बल्कि नेटवर्क पर स्थानांतरित एक फ़ाइल, एक संग्रह से एक फ़ाइल, एक डेटाबेस से एक फ़ाइल तक, एक फ़ाइल में जिसमें से सामग्री स्मृति में गतिशील रूप से उत्पन्न होती है। ई। "फ़ाइल पथ" इनपुट पैरामीटर के साथ एक विधि प्रदान करके, आप डेटा को डिस्क पर फिर से पढ़ने से पहले सहेजने के लिए अपने एपीआई के उपयोगकर्ता को उपकृत करते हैं। यह अर्थहीन ऑपरेशन गंभीर रूप से प्रदर्शन को प्रभावित करता है। एक ड्राइव एक बहुत धीमी चीज है। सुविधा के लिए, आप इनपुट पैरामीटर "फ़ाइल में पथ" के साथ एक विधि प्रदान कर सकते हैं, लेकिन अंदर हमेशा बाइट्स या स्ट्रीम के साथ इनपुट पर एक सार्वजनिक अतिभारित विधि का उपयोग करते हैं। एक "मार्कर" है जो आपको अतिरिक्त डिस्क लिखने / पढ़ने के संचालन को खोजने में मदद कर सकता है, अपने प्रोजेक्ट में मानक तरीकों का उपयोग करने का प्रयास करें: Path.GetTempPath() और Path.GetRandomFileName() (System.IO से)। संभावना की उच्च डिग्री के साथ, आप उपरोक्त समस्या या समान के एक समाधान को पूरा करेंगे।

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

3. थ्रेड को पैरामीटर के रूप में उपयोग करने से बचें और अपने तरीकों का परिणाम


यहाँ क्या समस्या है ... जब हमें कुछ "ब्लैक बॉक्स" से एक स्ट्रीम मिलती है, तो हमें इसकी स्थिति को ध्यान में रखना चाहिए। यानी क्या धारा खुली है? पढ़ना / लिखना मार्कर कहां है? क्या हमारे कोड की परवाह किए बिना इसकी स्थिति बदल सकती है? यदि स्ट्रीम स्ट्रीम को आधार वर्ग के रूप में घोषित किया जाता है, तो हमें इस बात की भी जानकारी नहीं है कि इस पर कौन से संचालन उपलब्ध हैं। यह सब अतिरिक्त चेक द्वारा हल किया जाता है, और यह अतिरिक्त कोड और लागत है। इसके अलावा, मैं बार-बार ऐसी स्थिति में आया, जहां कुछ "अस्पष्ट" पद्धति से स्ट्रीम प्राप्त करते समय, डेवलपर ने इसे सुरक्षित रूप से खेलना पसंद किया और इससे डेटा को पूरी तरह से नियंत्रित नए स्थानीय मेमोरीस्ट्रीम में "ट्रांसफर" कर दिया। हालांकि, स्रोत धारा काफी सुरक्षित हो सकती है। शायद यह भी पहले से ही MemoryStream पढ़ने के लिए तैयार किया गया था। कभी-कभी यह असावधानी के बिंदु तक पहुंच सकता है - एक विधि के अंदर, मेमोरीस्ट्रीम में बाइट्स की एक सरणी रखी जाती है, फिर इस मेमोरीस्ट्रीम को बेस स्ट्रीम के रूप में घोषित विधि के परिणाम के रूप में वापस किया जाता है। बाहर, यह स्ट्रीम एक नए मेमोरीस्ट्रीम में बदल जाती है, और फिर ToArray () बाइट्स की एक सरणी देता है, जो कि हमारे पास मूल रूप से था। अधिक सटीक रूप से, यह इसकी अगली प्रति होगी। विडंबना यह है कि हमारे तरीके के अंदर और बाहर, कोड पूरी तरह से सही है। मेरी राय में, यह उदाहरण मेरे सिर से बाहर नहीं है, लेकिन वाणिज्यिक कोड में कहीं पाया गया था।

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

4. एनमेट्स का इनहेरिटेंस


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



बेंचमार्क कोड
 public class CollectEnums { [Params(1000, 10000, 100000, 1000000)] public int N; [Benchmark] public EnumFromInt[] EnumOfInt() { EnumFromInt[] results = new EnumFromInt[N]; for (int i = 0; i < N; i++) { results[i] = EnumFromInt.Value1; } return results; } [Benchmark] public EnumFromByte[] EnumOfByte() { EnumFromByte[] results = new EnumFromByte[N]; for (int i = 0; i < N; i++) { results[i] = EnumFromByte.Value1; } return results; } } public enum EnumFromInt { Value1, Value2 } public enum EnumFromByte: byte { Value1, Value2 } 


5. कक्षाओं के बारे में कुछ और शब्द एरे और लिस्ट


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



बेंचमार्क कोड
 public class IterationBenchmark { private List<int> _list; private int[] _array; [Params(100000, 10000000)] public int N; [GlobalSetup] public void Setup() { const int MIN = 1; const int MAX = 10; Random rnd = new Random(); _list = Enumerable.Repeat(0, N).Select(i => rnd.Next(MIN, MAX)).ToList(); _array = _list.ToArray(); } [Benchmark] public int ForList() { int total = 0; for (int i = 0; i < _list.Count; i++) { total += _list[i]; } return total; } [Benchmark] public int ForeachList() { int total = 0; foreach (int i in _list) { total += i; } return total; } [Benchmark] public int ForeachArray() { int total = 0; foreach (int i in _array) { total += i; } return total; } [Benchmark] public int ForArray() { int total = 0; for (int i = 0; i < _array.Length; i++) { total += _array[i]; } return total; } } 


तथ्य यह है कि एक सरणी पर पुनरावृत्ति के लिए, "foreach" एक IEnumerable कार्यान्वयन का उपयोग नहीं करता है। इस विशेष मामले में, सूचकांक द्वारा सबसे अधिक अनुकूलित पुनरावृत्ति का प्रदर्शन किया जाता है, बिना सरणी के आउट-ऑफ-सीमा की जाँच के बिना, क्योंकि "फॉर्च्यूनर" निर्माण इंडेक्स के साथ काम नहीं करता है, इसलिए डेवलपर को कोड में "गड़बड़" करने का अवसर नहीं है। ऐसा नियम के लिए अपवाद है। इसलिए, यदि कोड के कुछ महत्वपूर्ण खंड में आपने अनुकूलन के लिए "foreach" के उपयोग को "for" के साथ बदल दिया, तो आपने खुद को पैर में गोली मार ली। कृपया ध्यान दें कि यह केवल सरणियों के लिए प्रासंगिक है। StackOverflow पर कई शाखाएँ हैं जहाँ इस सुविधा पर चर्चा की जाती है।

6. क्या हैश टेबल के माध्यम से खोज करना हमेशा उचित है?


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

 private static int GetNumber(string numberStr) { Dictionary<string, int> dictionary = new Dictionary<string, int> { {"One", 1}, {"Two", 2}, {"Three", 3} }; dictionary.TryGetValue(numberStr, out int result); return result; } 

हो सकता है कि आपके प्रोजेक्ट में भी कुछ ऐसा ही हो?

7. एंबेडिंग के तरीके


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

 [MethodImpl(MethodImplOptions.AggressiveInlining)] 

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

8. अनुमानित क्षमता


मैंने और मुझे आशा है कि अधिकांश डेवलपर्स ने भी) एक पलटा विकसित किया है: मैंने संग्रह को इनिशियलाइज़ किया - मैंने सोचा कि क्या इसके लिए कैपेसिटी सेट करना संभव है। हालांकि, संग्रह तत्वों की सही संख्या हमेशा अग्रिम में ज्ञात नहीं होती है। लेकिन यह इस पैरामीटर को अनदेखा करने का एक कारण नहीं है। उदाहरण के लिए, यदि, आपके संग्रह में कितने तत्व होंगे, इसके बारे में बात करते हुए, आप एक धुंधली "हजारों की संख्या" को मानते हैं, यह क्षमता को 1000 पर सेट करने का एक अवसर है। एक छोटा सा सिद्धांत, उदाहरण के लिए, डिफ़ॉल्ट रूप से सूची के लिए, क्षमता = 16, ताकि केवल 1000 तक पहुंच, सिस्टम तत्वों की 1008 (16 + 32 + 64 + 128 + 256 + 512) अतिरिक्त प्रतियां बनाएगा और अगले जीसी कॉल की दया के लिए 7 अस्थायी सरणियों का निर्माण करेगा। यानी यह सब काम बर्बाद हो जाएगा। इसके अलावा, क्षमता के रूप में, कोई भी सूत्र का उपयोग करने से मना करता है। यदि आपके संग्रह का आकार अन्य संग्रह का एक तिहाई माना जाता है, तो आप क्षमता को अन्य संग्रह के बराबर सेट कर सकते हैं ।ाउंट / 3. कैपेसिटी सेट करते समय, संग्रह के संभावित आकार की सीमा को समझना अच्छा है और यह मान कितनी बारीकी से वितरित किया गया है। हमेशा नुकसान की संभावना होती है, लेकिन अगर सही तरीके से उपयोग किया जाए, तो अनुमानित क्षमता आपको अच्छी जीत दिलाएगी।

9. हमेशा अपना कोड निर्दिष्ट करें।


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

वास्तविक कहानी इस नियम की पुष्टि करती है, लेकिन यदि आप आलस्य पढ़ते हैं, तो आप छोड़ सकते हैं
एक रात, अपने शौक प्रोजेक्ट में लगे रहने के दौरान, उन्होंने खुद को एक निश्चित स्तर से ऊपर कोड के एक सेक्शन के प्रदर्शन को बढ़ाने का काम निर्धारित किया। लेकिन यह साइट छोटी थी और इसके लिए कुछ विकल्प मौजूद थे। मैंने प्रलेखन में पाया कि, संस्करण C # 7.2 के साथ शुरू, "पठनीय" कीवर्ड का उपयोग संरचनाओं के लिए किया जा सकता है। और मेरे मामले में, अपरिवर्तनीय संरचनाओं का उपयोग किया गया था, एक शब्द "आसानी से" जोड़कर मुझे वही मिला जो मैं चाहता था, यहां तक ​​कि एक मार्जिन के साथ भी! प्रणाली, यह जानते हुए कि मेरी संरचनाएं बदलने का इरादा नहीं है, मेरे मामले के लिए बेहतर कोड उत्पन्न करने में सक्षम थी।

10. यदि संभव हो, तो सभी समाधान परियोजनाओं के लिए .NET के एक संस्करण का उपयोग करें


आपको यह सुनिश्चित करने का प्रयास करना चाहिए कि आपके आवेदन के भीतर सभी असेंबली .NET के एक ही संस्करण से संबंधित हैं। यह NuGet पैकेज (package.config / json में संपादित) और आपकी अपनी असेंबली (प्रोजेक्ट गुणों में संपादित) दोनों पर लागू होता है। यह रैम को बचाएगा और "कोल्ड" स्टार्ट को गति देगा, क्योंकि आपके एप्लिकेशन की मेमोरी में .NET के विभिन्न संस्करणों के लिए एक ही लाइब्रेरी की कोई कॉपी नहीं होगी। यह ध्यान देने योग्य है कि सभी मामलों में नहीं। .NET के विभिन्न संस्करण मेमोरी में प्रतियां उत्पन्न करेंगे। लेकिन यह मान लें कि .NET के एक ही संस्करण पर निर्मित एप्लिकेशन हमेशा बेहतर होता है। इसके अलावा, यह कई संभावित समस्याओं को समाप्त करता है जो इस लेख के दायरे से बाहर हैं। आपके द्वारा उपयोग किए जाने वाले सभी NuGet पैकेजों के समेकित संस्करण आपके एप्लिकेशन के प्रदर्शन को बेहतर बनाने में भी योगदान करेंगे।

कुछ उपयोगी उपकरण


ILSpy एक नि: शुल्क उपकरण है जो आपको बहाल विधानसभा स्रोत कोड को देखने की अनुमति देता है। यदि मेरे पास एक प्रश्न है जिसके बारे में .NET तंत्र अधिक कुशल है, तो सबसे पहले मैं ILSpy (और Google या StackOverflow नहीं) खोलता हूं, और पहले से ही मैं वहां देखता हूं कि इसे कैसे लागू किया जाता है। उदाहरण के लिए, यह जानने के लिए कि HTTP, HttpWebRequest या WebClient वर्ग के माध्यम से डेटा प्राप्त करने के लिए प्रदर्शन के संदर्भ में सबसे अच्छा उपयोग क्या है, बस ILSpy के माध्यम से उनके कार्यान्वयन को देखें। इस विशेष मामले में, WebClient HttpWebRequest पर क्रमशः एक आवरण है, इसका उत्तर स्पष्ट है। .NET स्रोत कोड डर के लायक नहीं हैं, वे समान साधारण प्रोग्रामर द्वारा लिखे गए हैं।

बेंचमार्कडॉटनेट बेंचमार्क की एक मुफ्त लाइब्रेरी है। एक सरल और सहज ज्ञान युक्त StopWatch है (System.Diagnostics से)। लेकिन कभी-कभी यह पर्याप्त नहीं होता है। चूंकि एक अच्छे तरीके से यह एक ही परिणाम को ध्यान में रखना आवश्यक है, लेकिन कई तुलनाओं का औसत, ओएस के प्रभाव को कम करने के लिए उनके मध्यस्थ की तुलना करना बेहतर है। इसके अलावा, आपको "कोल्ड स्टार्ट" और आवंटित मेमोरी की मात्रा को ध्यान में रखना होगा। ऐसे जटिल परीक्षणों के लिए, बेंचमार्कडॉटनेट बनाया गया था। यह लाइब्रेरी है जो .NET कोर डेवलपर्स आधिकारिक परीक्षणों में उपयोग करते हैं। पुस्तकालय का उपयोग करना आसान है, लेकिन अगर इसके लेखक अचानक इस पोस्ट को पढ़ते हैं, तो कृपया परिणाम तालिका की संरचना को प्रभावित करने के लिए अधिक सुविधाजनक अवसर दें।

U2U कंसल्टिंग परफॉर्मेंस एनालाइजर विजुअल स्टूडियो के लिए एक फ्री प्लग-इन है जो परफॉर्मेंस के लिहाज से कोड को बेहतर बनाने के टिप्स देता है। 100% इस विश्लेषक की सलाह पर भरोसा करने लायक नहीं है। चूंकि मैं एक ऐसी स्थिति में आया था जहां सलाह के एक टुकड़े ने मुझे थोड़ा आश्चर्यचकित किया और एक विस्तृत विश्लेषण के बाद यह वास्तव में गलत निकला। दुर्भाग्य से, यह उदाहरण खो गया है, इसलिए एक शब्द लें। हालाँकि, यदि आप इसका उपयोग सोच-समझकर करते हैं, तो यह एक बहुत ही उपयोगी उपकरण है। उदाहरण के लिए, वह सुझाव देगा कि myStr.Replace("*", "-") बजाय myStr.Replace('*', '-') का उपयोग करना अधिक कुशल है। और दो जहाँ LINQ में अभिव्यक्तियाँ बेहतर एक में संयुक्त हैं। ये सभी "मैचों पर अनुकूलन" हैं, लेकिन वे लागू करने में आसान हैं और कोड / जटिलता में वृद्धि नहीं करते हैं।

निष्कर्ष में


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

पोस्ट अपडेट्स के आधार पर PS अपडेट


ToList पर ToArray का लाभ .NET Core के लिए प्रासंगिक है। लेकिन अगर आप पुराने .NET फ्रेमवर्क का उपयोग करते हैं, तो ToList शायद आपके लिए बेहतर होगा। समस्या यह है कि .NET फ्रेमवर्क में, ToArray कॉल अपने आप में ToList कॉल की तुलना में काफी धीमी है। और इन नुकसानों के लिए तेजी से तत्वों तक पहुंच और कम सरणी भंडारण द्वारा मुआवजा नहीं दिया जा सकता है। सामान्य तौर पर, यह मुद्दा अधिक जटिल हो गया, क्योंकि IEnumerable को लागू करने वाले विभिन्न वर्गों में दक्षता के विभिन्न स्तरों के साथ ToArray और ToList के अलग-अलग कार्यान्वयन हो सकते हैं।

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

इन मुद्दों पर रचनात्मक टिप्पणियों के लिए KvanTTT और epetrukhin का धन्यवाद।

साथ ही, जैसा कि तारितिन ने कहा, "सील" कीवर्ड के लिए JIT संकलन चरण में अनुकूलन अभी भी मौजूद है। लेकिन, यह केवल 9 वें पैराग्राफ के सभी शोधों की पुष्टि करता है।

ऐसा लगता है कि सभी रचनात्मक टिप्पणियों को ध्यान में रखा गया है। मैं इन टिप्पणियों से बहुत प्रसन्न हूं। चूंकि मैंने खुद एक लेखक के रूप में प्रतिक्रिया प्राप्त की है और मैंने अपने लिए कुछ नया भी सीखा है।

Source: https://habr.com/ru/post/hi466931/


All Articles