यह काम करो, इसे साफ करो, इसे ठोस बनाओ, जब तक यह काम करने की आवश्यकता है इसे तेजी से काम करें ।
यह चीजों का सामान्य क्रम होना चाहिए। आपकी पहली प्राथमिकता कुछ ऐसा बनाना है जो स्वीकृति परीक्षणों को पारित कर देगा जो आवश्यकताओं से हटते हैं। यह आपकी पहली प्राथमिकता है क्योंकि यह आपके ग्राहक की पहली प्राथमिकता है; विकास की समय सीमा के भीतर कार्यात्मक आवश्यकताओं को पूरा करना। अगली प्राथमिकता स्वच्छ, पठनीय कोड लिखना है, जो समझना आसान है और इस प्रकार किसी भी WTFs के बिना आपकी पोस्टरिटी द्वारा बनाए रखा जा सकता है जब यह आवश्यक हो जाता है (यह लगभग "कभी" का सवाल नहीं है, तो आप या आपके जाने के बाद किसी को जाना होगा) वापस जाएं (कुछ बदलें / ठीक करें)। तीसरी प्राथमिकता यह है कि कोड को SOLID कार्यप्रणाली (या यदि आप चाहें तो GRASP) का पालन करें, जो कोड को मॉड्यूलर, पुन: प्रयोज्य, बदली जाने योग्य विखंडू में डालता है जो फिर से रखरखाव करता है (न केवल वे समझ सकते हैं कि आपने क्या किया और क्यों किया? लेकिन वहाँ स्वच्छ लाइनें हैं जिनके साथ मैं शल्य चिकित्सा को हटा सकता हूं और कोड के टुकड़े बदल सकता हूं)। अंतिम प्राथमिकता प्रदर्शन है; यदि कोड पर्याप्त महत्वपूर्ण है कि उसे प्रदर्शन चश्मा के अनुरूप होना है, तो यह निश्चित रूप से महत्वपूर्ण है कि इसे सही, स्वच्छ और ठोस बनाया जाए।
इकोस्टिंग क्रिस्टोफर (और डोनाल्ड नथ), "समय से पहले अनुकूलन सभी बुराई की जड़ है"। इसके अलावा, आप जिस प्रकार के अनुकूलन पर विचार कर रहे हैं, वे दोनों मामूली हैं (आपकी नई वस्तु का एक संदर्भ स्टैक पर बनाया जाएगा, चाहे आप इसे स्रोत कोड में नाम दें या नहीं) और एक प्रकार का जो संकलित में कोई अंतर पैदा नहीं कर सकता है। आईएल। परिवर्तनीय नामों को आईएल में आगे नहीं बढ़ाया जाता है, इसलिए जब से आप चर को इसके पहले (और शायद केवल) उपयोग करने से ठीक पहले घोषित कर रहे हैं, मैं कुछ बीयर मनी पर शर्त लगाऊंगा कि आईएल आपके दो उदाहरणों के बीच समान है। तो, आपका सहकर्मी 100% सही है; आप गलत जगह देख रहे हैं अगर आप नामांकित चर बनाम इनलाइन तात्कालिकता को देख रहे हैं ताकि कुछ का अनुकूलन हो सके।
.NET में माइक्रो-ऑप्टिमाइज़ेशन लगभग इसके लायक नहीं हैं (मैं 99.99% मामलों के बारे में बात कर रहा हूं)। C / C ++ में, हो सकता है, यदि आप जानते हैं कि आप क्या कर रहे हैं। .NET वातावरण में काम करते समय, आप पहले से ही हार्डवेयर की धातु से काफी दूर हैं कि कोड निष्पादन में महत्वपूर्ण ओवरहेड है। इसलिए, यह देखते हुए कि आप पहले से ही एक ऐसे वातावरण में हैं जो इंगित करता है कि आपने ब्लिस्टरिंग गति को छोड़ दिया है और इसके बजाय "सही" कोड लिखना चाहते हैं, अगर .NET वातावरण में कुछ वास्तव में तेजी से पर्याप्त काम नहीं कर रहा है, या तो इसकी जटिलता है बहुत अधिक है, या आपको इसे समानांतर करने पर विचार करना चाहिए। अनुकूलन के लिए अनुसरण करने के लिए यहां कुछ बुनियादी संकेत दिए गए हैं; मैं आपको अनुकूलन में आपकी उत्पादकता की गारंटी देता हूं (समय व्यतीत करने के लिए प्राप्त की गई गति) आसमान छू जाएगी:
- गुणांक बदलने से अधिक फ़ंक्शन आकार मायने रखता है - WRT बिग-ओह जटिलता, आप उन चरणों की संख्या कम कर सकते हैं जिन्हें एन 2 एल्गोरिथ्म में आधे से निष्पादित किया जाना चाहिए , और आपके पास अभी भी एक द्विघात-जटिलता एल्गोरिथ्म है, जिसमें यह निष्पादित होता है आधा समय यह इस्तेमाल किया। यदि इस प्रकार की समस्या के लिए यह जटिलता की निचली सीमा है, तो ऐसा ही हो, लेकिन अगर एक ही समस्या का NlogN, रैखिक या लघुगणक समाधान है, तो आप अपने पास मौजूद अनुकूलन को कम करके एल्गोरिदम को स्विच करके अधिक लाभ प्राप्त करेंगे।
- सिर्फ इसलिए कि आप जटिलता को नहीं देख सकते हैं इसका मतलब यह नहीं है कि यह आपको महंगा नहीं है - शब्द में बहुत से सुरुचिपूर्ण एक-लाइनर बहुत अच्छा प्रदर्शन करते हैं (उदाहरण के लिए, रेक्सक्स प्राइम चेकर एक घातीय-जटिलता फ़ंक्शन है, जबकि कुशल मुख्य मूल्यांकन जिसमें सभी वर्ग संख्याओं को उसकी वर्गमूल से कम संख्या में विभाजित करना शामिल है, O (Nlog (sqrt (N))) के क्रम पर है । Linq एक महान पुस्तकालय है क्योंकि यह कोड को सरल करता है, लेकिन SQL इंजन के विपरीत, .NET। संकलक अपनी क्वेरी को निष्पादित करने का सबसे कुशल तरीका खोजने का प्रयास नहीं करेगा। आपको यह जानना होगा कि जब आप किसी विधि का उपयोग करते हैं तो क्या होगा, और इस प्रकार एक विधि और तेज हो सकती है यदि उत्पादन करते समय पहले (या बाद में) श्रृंखला में रखा जाए। वही परिणाम।
- OTOH, हमेशा स्रोत जटिलता और रनटाइम जटिलता के बीच एक व्यापार है - SelectionSort को लागू करना बहुत आसान है; आप शायद इसे 10LOC या उससे कम में कर सकते हैं। MergeSort थोड़ा अधिक जटिल है, Quicksort अधिक है, और RadixSort और भी अधिक। लेकिन, जैसे-जैसे एल्गोरिथ्म कोडिंग जटिलता में वृद्धि होती है (और इस तरह "अप-फ्रंट" विकास समय), वे रनटाइम जटिलता में कमी करते हैं; MergeSort और QuickSort NlogN हैं, और RadixSort को आम तौर पर रैखिक माना जाता है (तकनीकी रूप से यह NlogM है जहाँ M N में सबसे बड़ी संख्या है)।
- तेजी से तोड़ें - अगर कोई ऐसा चेक है, जो सस्ते में बनाया जा सकता है, जिसके सही होने की काफी संभावना है और इसका मतलब है कि आप आगे बढ़ सकते हैं, तो पहले चेक करें। यदि आपका एल्गोरिथ्म, उदाहरण के लिए, केवल 1, 2, या 3 में समाप्त होने वाली संख्याओं की परवाह करता है, तो सबसे अधिक संभावना मामला (पूरी तरह से यादृच्छिक डेटा दिया गया) एक संख्या है जो कुछ अन्य अंकों में समाप्त होती है, इसलिए परीक्षण करें कि संख्या में अंत नहीं है 1, 2, या 3, यह देखने के लिए कि क्या 1, 2, या 3. में संख्या समाप्त होती है या नहीं, यह देखने के लिए कि क्या तर्क के एक टुकड़े के लिए A & B की आवश्यकता है, और P (A) = 0.9 जबकि P (B) = 0.1 है, तो जाँच करें B पहला, जब तक कि अगर! A तब! B (जैसे
if(myObject != null && myObject.someProperty == 1)
), या B मूल्यांकन करने के लिए A की तुलना में 9 गुना अधिक समय लेता है ( if(myObject != null && some10SecondMethodReturningBool())
)।
- ऐसा कोई भी प्रश्न न पूछें, जिसका उत्तर आपको पहले से पता हो - यदि आपके पास "फॉल-थ्रू" स्थितियों की एक श्रृंखला है, और उन स्थितियों में से एक या अधिक सरल स्थिति पर निर्भर हैं जिन्हें भी जांचना आवश्यक है, तो कभी भी दोनों की जांच न करें ये स्वतंत्र रूप से। उदाहरण के लिए, यदि आपके पास एक चेक है जिसके लिए A की आवश्यकता है, और A && B के लिए एक चेक की आवश्यकता है, तो आपको A की जाँच करनी चाहिए, और यदि आपको B की जाँच करनी चाहिए, तो A!, तो! A && B, को भी परेशान न करें।
- जितना अधिक बार आप कुछ करते हैं, उतना ही आपको ध्यान देना चाहिए कि यह कैसे किया जाता है - यह कई स्तरों पर विकास में एक सामान्य विषय है; एक सामान्य विकास के अर्थ में, "यदि एक सामान्य कार्य समय लेने वाला या काल्पनिक है, तो इसे तब तक करते रहें जब तक कि आप निराश और जानकार दोनों बेहतर तरीके से आने के लिए पर्याप्त न हों"। कोड शब्दों में, एक अक्षम एल्गोरिथ्म जितनी बार चलाया जाता है, उतना ही आप इसे अनुकूलित करके समग्र प्रदर्शन में प्राप्त करेंगे। प्रोफाइलिंग टूल हैं जो एक बाइनरी असेंबली और इसके डिबग प्रतीकों को ले सकते हैं और आपको दिखा सकते हैं, कुछ उपयोग के मामलों के माध्यम से चलने के बाद, कोड की कौन सी लाइनें सबसे ज्यादा चलती थीं। उन पंक्तियों, और उन पंक्तियों को चलाने वाली पंक्तियाँ, वे हैं जिन पर आपको सबसे अधिक ध्यान देना चाहिए, क्योंकि आपके द्वारा प्राप्त दक्षता में कोई भी वृद्धि कई गुना अधिक होगी।
- यदि आप इस पर पर्याप्त हार्डवेयर फेंकते हैं तो एक अधिक जटिल एल्गोरिथ्म एक कम जटिल एल्गोरिथ्म की तरह दिखता है । कुछ समय ऐसे होते हैं जहाँ आपको यह महसूस करना होता है कि आपका एल्गोरिथ्म सिस्टम की तकनीकी सीमाओं (या उसके हिस्से) के पास आ रहा है, जिस पर आप इसे चला रहे हैं; उस बिंदु से यदि इसे और तेज़ करने की आवश्यकता है, तो आप इसे बेहतर हार्डवेयर पर चलाकर अधिक लाभ प्राप्त करेंगे। यह समानांतरकरण पर भी लागू होता है; N 2 -complexity एल्गोरिथ्म, जब N कोर पर चलाया जाता है, तो रेखीय दिखता है। इसलिए, यदि आप सुनिश्चित हैं कि आप जिस प्रकार के एल्गोरिथ्म को लिख रहे हैं, उसके लिए निम्न जटिलता से टकराया है, तो "विभाजित और जीत" के तरीकों की तलाश करें।
- जब यह काफी तेजी से होता है तो तेज होता है - जब तक आप किसी विशेष चिप को लक्षित करने के लिए हाथ से पैकिंग करने वाले असेंबली नहीं होते, तब तक हमेशा कुछ न कुछ प्राप्त होता रहता है। हालाँकि, जब तक आप हाथ से पैकिंग करने वाले असेंबली नहीं बनना चाहते, आपको हमेशा यह ध्यान रखना होगा कि ग्राहक "काफी अच्छा" क्या कहेगा। फिर, "समय से पहले अनुकूलन सभी बुराई की जड़ है"; जब आपका ग्राहक इसे पर्याप्त तेज़ी से कहता है, तो आप तब तक कर सकते हैं जब तक वह यह नहीं सोचता कि यह अब और तेज़ नहीं है।