.NET कोर में प्रदर्शन

सभी को नमस्कार! यह लेख सर्वश्रेष्ठ प्रथाओं का एक संग्रह है, जिसे मैं और मेरे सहकर्मी लंबे समय से विभिन्न परियोजनाओं पर काम कर रहे हैं।
मशीन के बारे में जानकारी जिस पर गणना की गई थी:बेंचमार्कडॉटनेट = v0.11.5, ओएस = विंडोज 10.0.18362
इंटेल कोर i5-8250U सीपीयू 1.60GHz (काबी लेक आर), 1 सीपीयू, 8 तार्किक और 4 भौतिक कोर
.NET कोर एसडीके = 3.0.100
[मेजबान]: .NET कोर 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 बिट आईयूआईआईटी
कोर: .NET कोर 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 बिट RyuJIT
[होस्ट]: .NET कोर 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 बिट RyuJIT
कोर: .NET कोर 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 बिट RyuJIT
नौकरी = कोर रनटाइम = कोर
ToList vs ToArray and Cycles
मैंने .NET कोर 3.0 की रिलीज़ के साथ इस जानकारी को तैयार करने की योजना बनाई, लेकिन वे मुझसे आगे निकल गए, मैं किसी और की प्रसिद्धि की चोरी नहीं करना चाहता और किसी और की जानकारी को कॉपी करना नहीं चाहता, इसलिए मैं सिर्फ
एक अच्छे लेख के लिंक को इंगित करता हूं
जहां तुलना विस्तृत है ।
अपने आप से, मैं सिर्फ आपको अपने माप और परिणाम प्रस्तुत करना चाहता हूं, मैंने लूप लिखने के "सी ++ शैली" के प्रेमियों के लिए उनके साथ रिवर्स लूप जोड़े।
कोड:public class Bench { 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 random = new Random(); _list = Enumerable.Repeat(0, N).Select(i => random.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 ForListFromEnd() { int total = 0;t for (int i = _list.Count-1; i > 0; 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; } [Benchmark] public int ForArrayFromEnd() { int total = 0; for (int i = _array.Length-1; i > 0; i--) { total += _array[i]; } return total; } }
.NET कोर 2.2 और 3.0 में प्रदर्शन लगभग समान हैं। यहाँ मैं .NET कोर 3.0 में प्राप्त करने में कामयाब रहा:


हम यह निष्कर्ष निकाल सकते हैं कि प्रकार के संग्रह का लूप प्रसंस्करण तेज है, इसकी आंतरिक अनुकूलन और संग्रह के आकार के स्पष्ट आवंटन के कारण। यह भी याद रखने योग्य है कि प्रकार सूची के एक संग्रह के अपने फायदे हैं और आपको आवश्यक गणनाओं के आधार पर वांछित संग्रह का उपयोग करना चाहिए। यहां तक कि अगर आप साइकिल के साथ काम करने का तर्क लिखते हैं, तो यह मत भूलो कि यह एक साधारण लूप है और यह चक्र के संभावित अनुकूलन के अधीन भी है। एक लेख लंबे समय तक habr पर दिखाई दिया:
https://habr.com/en/post/124910/ । यह अभी भी प्रासंगिक है और पढ़ने के लिए अनुशंसित है।
फेंक
एक साल पहले, मैंने एक विरासत परियोजना पर एक कंपनी में काम किया था, उस परियोजना में यह एक कोशिश-कैच-थ्रो निर्माण के माध्यम से क्षेत्र सत्यापन को संभालने के लिए सामान्य के दायरे में था। मैं पहले ही समझ गया था कि यह परियोजना का एक अस्वास्थ्यकर व्यावसायिक तर्क था, इसलिए मैंने कोशिश की कि यदि संभव हो तो इस तरह के डिजाइन का उपयोग न करें। लेकिन आइए देखें कि इस तरह के डिजाइन के साथ त्रुटियों को संभालने के लिए बुरा दृष्टिकोण क्या है। मैंने दो दृष्टिकोणों की तुलना करने के लिए थोड़ा कोड लिखा और प्रत्येक विकल्प के लिए "बेंच" को गोली मार दी।
कोड: public bool ContainsHash() { bool result = false; foreach (var file in _files) { var extension = Path.GetExtension(file); if (_hash.Contains(extension)) result = true; } return result; } public bool ContainsHashTryCatch() { bool result = false; try { foreach (var file in _files) { var extension = Path.GetExtension(file); if (_hash.Contains(extension)) result = true; } if(!result) throw new Exception("false"); } catch (Exception e) { result = false; } return result; }
.NET कोर 3.0 और कोर 2.2 में परिणाम एक समान परिणाम (.NET कोर 3.0) हैं:


पकड़ने का प्रयास करें कोड की समझ को जटिल करता है और आपके कार्यक्रम के निष्पादन समय को बढ़ाता है। लेकिन अगर आपको इस निर्माण की आवश्यकता है, तो आपको कोड की उन पंक्तियों को नहीं डालना चाहिए जिनसे त्रुटि से निपटने की उम्मीद नहीं है - इससे कोड को समझने में आसानी होगी। वास्तव में, यह इतना अपवाद हैंडलिंग नहीं है जो सिस्टम को लोड कर रहा है क्योंकि थ्रो नए अपवाद निर्माण के माध्यम से त्रुटियों को स्वयं फेंक रहा है।
अपवादों को फेंकना किसी भी वर्ग की तुलना में धीमा है जो वांछित प्रारूप में एक त्रुटि एकत्र करता है। यदि आप एक फॉर्म या कोई डेटा प्रोसेस कर रहे हैं और स्पष्ट रूप से जानते हैं कि त्रुटि क्या होनी चाहिए, तो इसे प्रोसेस क्यों न करें?
यदि आपको यह स्थिति असाधारण नहीं है, तो आपको नया अपवाद नहीं लिखना चाहिए।
एक अपवाद को संभालना और फेंकना बहुत महंगा है !!!ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant
.NET प्लेटफ़ॉर्म पर अपने 5 वर्षों के अनुभव के साथ, उन्होंने कई परियोजनाओं को पूरा किया है जो स्ट्रिंग मिलान का उपयोग करते हैं। मैंने निम्न चित्र भी देखा: कई परियोजनाओं के साथ एक एंटरप्राइज़ समाधान था, जिनमें से प्रत्येक ने विभिन्न तरीकों से स्ट्रिंग तुलना की। लेकिन क्या उपयोग करने लायक है और इसे कैसे एकजुट करना है? रिक्टर के CLR में C # के माध्यम से, मैंने पढ़ा कि ToUpperInvariant () ToLowerInvariant () से अधिक तेज़ है।
पुस्तक से कतरन:

बेशक, मैंने इसे नहीं माना और कुछ परीक्षण वापस करने का फैसला किया। फिर .NET फ्रेमवर्क पर परिणाम आया और मुझे झटका लगा - 15% से अधिक प्रदर्शन में वृद्धि। अगली सुबह काम पर आने के बाद मैंने अपने वरिष्ठों को ये माप दिखाए और उन्हें स्रोत तक पहुँचा दिया। उसके बाद, 14 में से 2 परियोजनाओं को नए मापों के लिए बदल दिया गया था, और यह देखते हुए कि इन दोनों परियोजनाओं में विशाल एक्सेल तालिकाओं को संसाधित करने के लिए मौजूद था, परिणाम उत्पाद के लिए महत्वपूर्ण से अधिक था।
मैं आपको .NET कोर के विभिन्न संस्करणों के लिए माप भी प्रस्तुत करता हूं, ताकि आप में से प्रत्येक सबसे इष्टतम समाधान की दिशा में एक विकल्प बना सके। और मैं बस उस कंपनी में जोड़ना चाहता हूं जहां मैं काम करता हूं, हम तार की तुलना करने के लिए ToUpper () का उपयोग करते हैं।
कोड: public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3"; [Benchmark] public bool ToLower() { return defaultString.ToLower() == defaultString.ToLower(); } [Benchmark] public bool ToLowerInvariant() { return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant(); } [Benchmark] public bool ToUpper() { return defaultString.ToUpper() == defaultString.ToUpper(); } [Benchmark] public bool ToUpperInvariant() { return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant(); }
; public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3"; [Benchmark] public bool ToLower() { return defaultString.ToLower() == defaultString.ToLower(); } [Benchmark] public bool ToLowerInvariant() { return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant(); } [Benchmark] public bool ToUpper() { return defaultString.ToUpper() == defaultString.ToUpper(); } [Benchmark] public bool ToUpperInvariant() { return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant(); }


.NET कोर 3.0 में, इन विधियों में से प्रत्येक के लिए लाभ ~ x2 है और आपस में कार्यान्वयन को संतुलित करता है।


टियर संकलन
अपने पिछले लेख में मैंने संक्षेप में इस कार्यक्षमता का वर्णन किया है, मैं अपने शब्दों को सही करना और पूरक करना चाहूंगा। बहुस्तरीय संकलन आपके समाधान के लॉन्च समय को गति देता है, लेकिन आप बलिदान करते हैं कि आपके कोड के कुछ हिस्से पृष्ठभूमि में अधिक अनुकूलित संस्करण में संकलित होंगे, जिससे छोटे ओवरहेड हो सकते हैं। NET Core 3.0 के आगमन के साथ, टीयर संकलन के साथ परियोजनाओं के निर्माण का समय कम हो गया और इस तकनीक से संबंधित फिक्स्ड कीड़े हो गए। पहले, इस तकनीक ने ASP.NET कोर में पहले अनुरोधों में त्रुटियों का कारण बना और मल्टीलेवल संकलन मोड में पहले निर्माण के दौरान जमा देता है। वर्तमान में, यह .NET कोर 3.0 में डिफ़ॉल्ट रूप से सक्षम है, लेकिन आप इसे इच्छानुसार अक्षम कर सकते हैं। यदि आप टीम-लीड, वरिष्ठ, मध्य की स्थिति में हैं या आप विभाग के प्रमुख हैं, तो आपको यह समझना चाहिए कि परियोजना के तेजी से विकास से टीम का मूल्य बढ़ता है और यह तकनीक आपको डेवलपर्स के समय और परियोजना के समय दोनों को बचाने की अनुमति देगी।
.NET स्तर ऊपर
अपने .NET फ्रेमवर्क / .NET कोर को अपग्रेड करें। अक्सर, प्रत्येक नया संस्करण एक अतिरिक्त प्रदर्शन को बढ़ावा देता है और नई सुविधाएँ जोड़ता है।
लेकिन वास्तव में क्या लाभ हैं? आइए उनमें से कुछ को देखें:
- .NET कोर 3.0 में, R2R चित्र प्रस्तुत किए गए हैं जो .NET कोर अनुप्रयोगों के स्टार्टअप समय को कम कर देंगे।
- संस्करण 2.2 ने टियर संकलन पेश किया, जिसकी बदौलत प्रोग्रामर किसी प्रोजेक्ट को लॉन्च करने में कम समय लगाते हैं।
- नए .NET मानक के लिए समर्थन।
- प्रोग्रामिंग भाषा के नए संस्करण के लिए समर्थन।
- अनुकूलन, प्रत्येक नए संस्करण के साथ, बेस लाइब्रेरीज़ कलेक्शन / स्ट्रक्चर / स्ट्रीम / स्ट्रिंग / रेगेक्स द्वारा ऑप्टिमाइज़ेशन में सुधार किया जाता है। यदि आप .NET फ्रेमवर्क से .NET कोर में अपग्रेड करते हैं, तो आपको एक बड़ा प्रदर्शन बूस्ट मिलेगा। उदाहरण के लिए, मैं .NET कोर 3.0 में जोड़े गए अनुकूलन के एक भाग के लिए एक लिंक संलग्न करता हूं: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

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