performance - अंतिम उपाय की प्रदर्शन अनुकूलन रणनीतियों




optimization language-agnostic (20)

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

चलो मान लो:

  • कोड पहले से ही सही ढंग से काम कर रहा है
  • चयनित एल्गोरिदम पहले से ही समस्या की परिस्थितियों के लिए इष्टतम हैं
  • कोड मापा गया है, और अपमानजनक दिनचर्या अलग कर दी गई है
  • ऑप्टिमाइज़ करने के सभी प्रयासों को यह भी सुनिश्चित करने के लिए मापा जाएगा कि वे मामले को और खराब नहीं करते हैं

जो मैं यहां खोज रहा हूं वह रणनीतिक और चाल है जो पिछले कुछ प्रतिशत तक एक महत्वपूर्ण एल्गोरिदम में निचोड़ने के लिए है जब ऐसा करने के लिए कुछ भी नहीं बचा है लेकिन जो कुछ भी लेता है।

आदर्श रूप से, जवाब भाषा अज्ञेयवादी बनाने का प्रयास करें, और लागू होने वाली सुझाई गई रणनीतियों के लिए किसी भी नीचे की तरफ इंगित करें।

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


अधिक सुझाव:

  • I / O से बचें : किसी भी I / O (डिस्क, नेटवर्क, बंदरगाहों, आदि) गणना करने वाले किसी भी कोड से हमेशा धीमे होने जा रहे हैं, इसलिए किसी भी I / O से छुटकारा पाएं जिसे आपको सख्ती से आवश्यकता नहीं है।

  • I / O ऊपर-सामने ले जाएं : गणना के लिए आवश्यक सभी डेटा को लोड करें, ताकि आपने दोहराया नहीं है I / O महत्वपूर्ण एल्गोरिदम के मूल में प्रतीक्षा करता है (और शायद परिणामस्वरूप दोहराया जा सकता है डिस्क चाहता है, एक हिट में सभी डेटा लोड करते समय मांग से बच सकते हैं)।

  • देरी I / O : गणना समाप्त होने तक अपने परिणामों को न लिखें, उन्हें डेटा संरचना में संग्रहित करें और फिर कड़ी मेहनत के दौरान अंत में एक ही समय में डंप करें।

  • थ्रेडेड I / O : उन लोगों के लिए जो पर्याप्त साहसी हैं, लोडिंग को समानांतर धागे में ले जाकर वास्तविक गणना के साथ 'I / O अप-फ्रंट' या 'देरी I / O' को गठबंधन करें, ताकि जब आप अधिक डेटा लोड कर रहे हों तो आप काम कर सकते हैं आपके पास पहले से मौजूद डेटा की गणना पर, या जब आप डेटा के अगले बैच की गणना करते हैं तो आप अंतिम बैच से परिणामों को एक साथ लिख सकते हैं।


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

ये वे प्रभाव हैं जिन्हें आपको प्रबंधित करने की आवश्यकता है। कभी-कभी आपके कोड को माइक्रो प्रबंधित करने के माध्यम से, लेकिन कभी-कभी सावधानीपूर्वक विचार और रिफैक्टरिंग के माध्यम से।

बहुत सी टिप्पणियां पहले से ही कैश अनुकूल कोड का उल्लेख करती हैं। इसके कम से कम दो विशिष्ट स्वाद हैं:

  • स्मृति लाने लेटेंसी से बचें।
  • लोअर मेमोरी बस प्रेशर (बैंडविड्थ)।

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

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

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


उस पर अधिक हार्डवेयर फेंको!


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

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

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

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

सूचकांक, सूचकांक, सूचकांक। और यदि आपके डेटाबेस पर लागू होते हैं तो उन आंकड़ों को अपडेट करें।

क्वेरी को sargable बनाओ। मतलब उन चीज़ों से बचें जो इंडेक्स का उपयोग करना असंभव बनाते हैं जैसे कि किसी तरह के क्लॉज के पहले अक्षर में वाइल्डकार्ड का उपयोग करना या शामिल होने वाले फ़ंक्शन या जहां कथन के बाएं भाग के रूप में।

सही डेटा प्रकार का प्रयोग करें। स्ट्रिंग डेटाटाइप को दिनांक डेटाटाइप में कनवर्ट करने की कोशिश करने के बजाय दिनांक फ़ील्ड पर दिनांक गणित करना तेज़ है, फिर गणना करें।

ट्रिगर में किसी भी प्रकार का लूप कभी न डालें!

अधिकांश डेटाबेस में यह जांचने का एक तरीका होता है कि क्वेरी निष्पादन कैसे किया जाएगा। माइक्रोसॉफ्ट एसक्यूएल सर्वर में इसे निष्पादन योजना कहा जाता है। समस्या क्षेत्रों के झूठ कहां देखने के लिए पहले उनको जांचें।

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

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

प्रोफाइलर आपको यह जानने में भी मदद करेगा कि कौन अवरुद्ध कर रहा है। कुछ प्रश्न जो अकेले चलते समय तुरंत निष्पादित करते हैं, वे अन्य प्रश्नों के ताले के कारण वास्तव में धीमे हो सकते हैं।


ठीक है, आप समस्या को परिभाषित कर रहे हैं जहां यह प्रतीत होता है कि सुधार के लिए ज्यादा जगह नहीं है। यह मेरे अनुभव में काफी दुर्लभ है। मैंने नवंबर '9 3 में डॉ। डॉब्स लेख में एक पारंपरिक रूप से अच्छी तरह से डिज़ाइन किए गए गैर-तुच्छ कार्यक्रम से शुरू करके इसे स्पष्ट अपशिष्ट के साथ शुरू करने की कोशिश की और इसे ऑप्टिमाइज़ेशन की एक श्रृंखला के माध्यम से ले जाने तक इसकी दीवार घड़ी का समय 48 से कम हो गया सेकंड सेकंड के लिए सेकंड, और स्रोत कोड आकार 4 के एक कारक से कम किया गया था। मेरा निदान उपकरण यह था । परिवर्तनों का अनुक्रम यह था:

  • पहली समस्या मिली सूची क्लस्टर (जिसे अब "इटरेटर" और "कंटेनर क्लासेस" कहा जाता है) का उपयोग आधे से अधिक समय तक लेखांकन था। उनको काफी सरल कोड के साथ बदल दिया गया, जिससे समय 20 सेकंड तक पहुंच गया।

  • अब सबसे बड़ा समय लेने वाला अधिक सूची निर्माण है। एक प्रतिशत के रूप में, यह पहले इतना बड़ा नहीं था, लेकिन अब ऐसा इसलिए है क्योंकि बड़ी समस्या को हटा दिया गया था। मुझे इसे तेज करने का एक तरीका मिल गया है, और समय 17 सेकंड तक गिर जाता है।

  • अब स्पष्ट अपराधियों को ढूंढना मुश्किल है, लेकिन कुछ छोटे हैं जिनके बारे में मैं कुछ कर सकता हूं, और समय 13 सेकंड तक गिर जाता है।

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

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

  • उस रीडिज़ाइन को किया जाता है, स्रोत कोड को 4 के कारक से कम कर देता है, और समय कम हो जाता है 10 सेकंड तक।

अब, क्योंकि यह बहुत तेज़ी से हो रहा है, नमूना करना मुश्किल है, इसलिए मैं इसे 10 गुना अधिक काम देता हूं, लेकिन निम्नलिखित समय मूल वर्कलोड पर आधारित होते हैं।

  • अधिक निदान से पता चलता है कि यह कतार प्रबंधन में समय बिता रहा है। इन-अस्तर में ये समय 7 सेकंड तक कम कर देता है।

  • अब एक बड़ा समय लेने वाला डायग्नोस्टिक प्रिंटिंग है जो मैं कर रहा था। फ्लश करें - 4 सेकंड।

  • अब सबसे बड़ा समय लेने वालों को मॉलोक और मुफ्त में कॉल किया जाता है। रीसायकल ऑब्जेक्ट्स - 2.6 सेकंड्स।

  • नमूना जारी रखते हुए, मुझे अभी भी ऐसे ऑपरेशन मिलते हैं जो सख्ती से आवश्यक नहीं हैं - 1.1 सेकंड।

कुल गति कारक: 43.6

अब कोई भी दो कार्यक्रम समान नहीं हैं, लेकिन गैर खिलौने सॉफ्टवेयर में मैंने हमेशा इस तरह की प्रगति देखी है। सबसे पहले आप आसानी से सामान प्राप्त करते हैं, और फिर अधिक कठिन, जब तक आप कम रिटर्न के बिंदु तक नहीं पहुंच जाते। फिर जब तक आप फिर से कम रिटर्न नहीं देते हैं, तब तक आपके द्वारा हासिल की जाने वाली अंतर्दृष्टि गतिशीलता के एक नए दौर को शुरू करने के लिए एक नया स्वरूप हो सकती है। अब यह वह बिंदु है जिस पर यह आश्चर्य हो सकता है कि ++i या i++ या for(;;) या while(1) तेज़ हैं: ऐसे प्रश्न जो मैं अक्सर SO पर देखता हूं।

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

जोड़ा गया: jerryjvl ने कुछ उदाहरणों का अनुरोध किया। यहां पहली समस्या है। इसमें कोड की अलग-अलग पंक्तियों की एक छोटी संख्या होती है, साथ में आधा समय लेना:

 /* IF ALL TASKS DONE, SEND ITC_ACKOP, AND DELETE OP */
if (ptop->current_task >= ILST_LENGTH(ptop->tasklist){
. . .
/* FOR EACH OPERATION REQUEST */
for ( ptop = ILST_FIRST(oplist); ptop != NULL; ptop = ILST_NEXT(oplist, ptop)){
. . .
/* GET CURRENT TASK */
ptask = ILST_NTH(ptop->tasklist, ptop->current_task)

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

दो अलग-अलग पंक्तियों में दूसरी समस्या यहां दी गई है:

 /* ADD TASK TO TASK LIST */ 
ILST_APPEND(ptop->tasklist, ptask)
. . .
/* ADD TRANSACTION TO TRANSACTION QUEUE */
ILST_APPEND(trnque, ptrn)

ये वस्तुओं को अपने सिरों पर जोड़कर सूचियां बना रहे हैं। (फिक्स एरे में वस्तुओं को इकट्ठा करना था, और एक ही सूची में सभी को एक साथ बनाना था।) दिलचस्प बात यह है कि इन वक्तव्यों को केवल मूल लागत के 3/48 (यानी कॉल स्टैक पर) लागत थी, इसलिए वे अंदर नहीं थे वास्तव में शुरुआत में एक बड़ी समस्या है। हालांकि, पहली समस्या को हटाने के बाद, उन्हें समय के 3/20 की लागत थी और इसलिए अब एक "बड़ी मछली" थी। आम तौर पर, यह कैसे चला जाता है।

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

संदर्भ जोड़ा गया: स्रोत कोड, मूल और पुन: डिजाइन दोनों, 1 99 3 के लिए, www.ddj.com में, फ़ाइल 9311.zip में, फाइल slug.asc और slug.zip में पाया जा सकता है।

संपादित करें 2011/11/26: अब एक स्रोत फोर्ज प्रोजेक्ट है जिसमें विजुअल सी ++ में सोर्स कोड और एक टर्न-बाय-फ्लाइट विवरण है जिसे इसे ट्यून किया गया था। यह केवल ऊपर वर्णित परिदृश्य के पहले भाग के माध्यम से जाता है, और यह बिल्कुल उसी अनुक्रम का पालन नहीं करता है, लेकिन अभी भी परिमाण गतिशीलता का 2-3 क्रम प्राप्त होता है।


मुझे लगता है कि यह पहले से ही एक अलग तरीके से कहा जा चुका है। लेकिन जब आप एक प्रोसेसर गहन एल्गोरिदम से निपट रहे हैं, तो आपको बाकी सब कुछ के खर्च पर सबसे आंतरिक लूप के अंदर सब कुछ सरल बनाना चाहिए।

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

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


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

  • ... अगर यह स्मृति है - "टाइम ऑफ कंप्यूटर प्रोग्रामिंग" श्रृंखला में से एक, Knuth द्वारा लिखे गए पुस्तकों में से एक को ढूंढें। सबसे अधिक संभावना यह सॉर्टिंग और खोज के बारे में है - अगर मेरी याददाश्त गलत है तो आपको पता लगाना होगा कि वह धीमे टेप डेटा स्टोरेज से निपटने के तरीके के बारे में बात करता है। मानसिक रूप से अपनी याददाश्त / टेप जोड़ी को क्रमशः कैश / मुख्य मेमोरी (या एल 1 / एल 2 कैश की जोड़ी में) में बदल दें। उन्होंने बताई गई सभी युक्तियों का अध्ययन करें - यदि आपको कुछ ऐसी समस्या मिलती है जो आपकी समस्या का समाधान करती है, तो पेशेवर कंप्यूटर वैज्ञानिक को पेशेवर शोध करने के लिए किराए पर लें। यदि आपकी मेमोरी समस्या एफएफटी के साथ मौका है (रेडिक्स -2 तितलियों को करते समय कैश बिट-रिवर्स इंडेक्स पर चूक जाता है) तो एक वैज्ञानिक को किराए पर न लें - इसके बजाए मैन्युअल रूप से ऑप्टिमाइज़ एक-एक करके गुजरता है जब तक आप जीत या प्राप्त नहीं कर लेते मृत अंत करने के लिए। आपने पिछले कुछ प्रतिशत तक निचोड़ का उल्लेख किया है? यदि यह वास्तव में कुछ है तो आप सबसे अधिक संभावना जीतेंगे।

  • ... अगर यह प्रोसेसर है - असेंबली भाषा में स्विच करें। अध्ययन प्रोसेसर विनिर्देश - क्या टिकता है, वीएलआईडब्ल्यू, सिम। फंक्शन कॉल सबसे अधिक संभावना बदलने योग्य टिक-खाने वाले हैं। लूप ट्रांसफॉर्मेशन जानें - पाइपलाइन, अनलोल करें। गुण और विभाजन बिट बदलावों के साथ प्रतिस्थापन / इंटरपोलेटेड हो सकते हैं (छोटे पूर्णांक द्वारा गुणा किया जा सकता है अतिरिक्त के साथ बदला जा सकता है)। छोटे डेटा के साथ चाल का प्रयास करें - यदि आप 64 बिट्स के साथ भाग्यशाली एक निर्देश हैं तो 32 बिट पर दो या 16 या 8 पर 4 बिट्स के साथ प्रतिस्थापन योग्य हो सकता है। लंबे डेटा का प्रयास करें - उदाहरण के लिए आपकी फ्लोट गणना विशेष प्रोसेसर पर डबल से धीमी हो सकती है। यदि आपके पास त्रिकोणमितीय सामान है, तो इसे पूर्व-गणना वाले तालिकाओं से लड़ें; यह भी ध्यान रखें कि छोटे मूल्य की साइन को उस मूल्य के साथ प्रतिस्थापित किया जा सकता है यदि परिशुद्धता का नुकसान अनुमत सीमा के भीतर है।

  • ... यदि यह नेटवर्क है - उस डेटा को संपीड़ित करने के बारे में सोचें जिसे आप पार करते हैं। बाइनरी के साथ एक्सएमएल स्थानांतरण बदलें। अध्ययन प्रोटोकॉल। यदि आप डेटा हानि को किसी भी तरह से संभाल सकते हैं तो टीसीपी के बजाय यूडीपी आज़माएं।

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

एचटीएच :)


सुझाव:

  • पुनः गणना करने के बजाए पूर्व-गणना करें : किसी भी लूप या दोहराए गए कॉल जिनमें गणना की अपेक्षाकृत सीमित सीमा होती है, एक लुकअप (सरणी या शब्दकोश) बनाने पर विचार करें जिसमें वैध मान में सभी मानों के लिए उस गणना का नतीजा शामिल है आदानों। फिर इसके बजाय एल्गोरिदम के अंदर एक साधारण लुकअप का उपयोग करें।
    नीचे की ओर : यदि पूर्व-गणना वाले कुछ मान वास्तव में उपयोग किए जाते हैं तो इससे मामलों को और भी खराब हो सकता है, लुकअप भी महत्वपूर्ण स्मृति ले सकता है।
  • लाइब्रेरी विधियों का उपयोग न करें : अधिकांश पुस्तकालयों को परिदृश्यों की एक विस्तृत श्रृंखला के तहत सही ढंग से संचालित करने के लिए लिखा जाना चाहिए, और पैरामीटर पर शून्य जांच करना आदि। विधि को फिर से कार्यान्वित करके आप बहुत सारे तर्क को दूर करने में सक्षम हो सकते हैं आप जिस परिस्थिति का उपयोग कर रहे हैं उसमें लागू नहीं होता है।
    नीचे की तरफ : अतिरिक्त कोड लिखना मतलब है कि बग के लिए अधिक सतह क्षेत्र।
  • लाइब्रेरी विधियों का उपयोग करें : खुद के विरोधाभास के लिए, भाषा पुस्तकालय उन लोगों द्वारा लिखे गए हैं जो आपके या मेरे से बहुत चालाक हैं; बाधाएं हैं कि उन्होंने इसे बेहतर और तेज़ किया। इसे तब तक लागू न करें जब तक कि आप इसे वास्तव में तेज़ी से नहीं बना सकते (यानी: हमेशा उपाय करें!)
  • धोखा : कुछ मामलों में हालांकि आपकी समस्या के लिए एक सटीक गणना मौजूद हो सकती है, आपको 'सटीक' की आवश्यकता नहीं हो सकती है, कभी-कभी अनुमान 'पर्याप्त पर्याप्त' हो सकता है और सौदा में बहुत तेज़ हो सकता है। अपने आप से पूछें, क्या वास्तव में कोई फर्क पड़ता है अगर उत्तर 1% से बाहर है? 5%? यहां तक ​​कि 10%?
    नीचे की तरफ : अच्छा ... जवाब सटीक नहीं होगा।

Did you know that a CAT6 cable is capable of 10x better shielding off extrenal inteferences than a default Cat5e UTP cable?

For any non-offline projects, while having best software and best hardware, if your throughoutput is weak, then that thin line is going to squeeze data and give you delays, albeit in milliseconds... but if you are talking about the last drops, that's a some drops gained, 24/7 for any packge sent or received.


Reduce variable sizes (in embedded systems)

If your variable size is larger than the word size on a specific architecture, it can have a significant effect on both code size and speed. For example, if you have a 16 bit system, and use a long int variable very often, and later realize that it can never get outside the range (−32.768 ... 32.767) consider reducing it to short int.

From my personal experience, if a program is ready or almost ready, but we realize it takes up about 110% or 120% of the target hardware's program memory, a quick normalization of variables usually solves the problem more often than not.

By this time, optimizing the algorithms or parts of the code itself can become frustratingly futile:

  • reorganize the whole structure and the program no longer works as intended, or at least you introduce a lot of bugs.
  • do some clever tricks: usually you spend a lot of time optimizing something, and discover no or very small decrease in code size, as the compiler would have optimized it anyway.

Many people make the mistake of having variables which exactly store the numerical value of a unit they use the variable for: for example, their variable time stores the exact number of milliseconds, even if only time steps of say 50 ms are relevant. Maybe if your variable represented 50 ms for each increment of one, you would be able to fit into a variable smaller or equal to the word size. On an 8 bit system, for example, even a simple addition of two 32-bit variables generates a fair amount of code, especially if you are low on registers, while 8 bit additions are both small and fast.


कैशिंग! लगभग कुछ भी तेज़ बनाने के लिए एक सस्ता तरीका (प्रोग्रामर प्रयास में) अपने प्रोग्राम के किसी भी डेटा आंदोलन क्षेत्र में कैशिंग अबास्ट्रक्शन परत जोड़ना है। यह I / O हो या बस वस्तुओं या संरचनाओं का निर्माण / निर्माण हो। फैक्ट्री कक्षाओं और पाठक / लेखकों को कैश जोड़ने में अक्सर आसान होता है।

Sometimes the cache will not gain you much, but it's an easy method to just add caching all over and then disable it where it doesn't help. I've often found this to gain huge performance without having to micro-analyse the code.


विभाजन और जीत

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


I've spent some time working on optimising client/server business systems operating over low-bandwidth and long-latency networks (eg satellite, remote, offshore), and been able to achieve some dramatic performance improvements with a fairly repeatable process.

  • Measure : Start by understanding the network's underlying capacity and topology. Talking to the relevant networking people in the business, and make use of basic tools such as ping and traceroute to establish (at a minimum) the network latency from each client location, during typical operational periods. Next, take accurate time measurements of specific end user functions that display the problematic symptoms. Record all of these measurements, along with their locations, dates and times. Consider building end-user "network performance testing" functionality into your client application, allowing your power users to participate in the process of improvement; empowering them like this can have a huge psychological impact when you're dealing with users frustrated by a poorly performing system.

  • Analyze : Using any and all logging methods available to establish exactly what data is being transmitted and received during the execution of the affected operations. Ideally, your application can capture data transmitted and received by both the client and the server. If these include timestamps as well, even better. If sufficient logging isn't available (eg closed system, or inability to deploy modifications into a production environment), use a network sniffer and make sure you really understand what's going on at the network level.

  • Cache : Look for cases where static or infrequently changed data is being transmitted repetitively and consider an appropriate caching strategy. Typical examples include "pick list" values or other "reference entities", which can be surprisingly large in some business applications. In many cases, users can accept that they must restart or refresh the application to update infrequently updated data, especially if it can shave significant time from the display of commonly used user interface elements. Make sure you understand the real behaviour of the caching elements already deployed - many common caching methods (eg HTTP ETag) still require a network round-trip to ensure consistency, and where network latency is expensive, you may be able to avoid it altogether with a different caching approach.

  • Parallelise : Look for sequential transactions that don't logically need to be issued strictly sequentially, and rework the system to issue them in parallel. I dealt with one case where an end-to-end request had an inherent network delay of ~2s, which was not a problem for a single transaction, but when 6 sequential 2s round trips were required before the user regained control of the client application, it became a huge source of frustration. Discovering that these transactions were in fact independent allowed them to be executed in parallel, reducing the end-user delay to very close to the cost of a single round trip.

  • Combine : Where sequential requests must be executed sequentially, look for opportunities to combine them into a single more comprehensive request. Typical examples include creation of new entities, followed by requests to relate those entities to other existing entities.

  • Compress : Look for opportunities to leverage compression of the payload, either by replacing a textual form with a binary one, or using actual compression technology. Many modern (ie within a decade) technology stacks support this almost transparently, so make sure it's configured. I have often been surprised by the significant impact of compression where it seemed clear that the problem was fundamentally latency rather than bandwidth, discovering after the fact that it allowed the transaction to fit within a single packet or otherwise avoid packet loss and therefore have an outsize impact on performance.

  • Repeat : Go back to the beginning and re-measure your operations (at the same locations and times) with the improvements in place, record and report your results. As with all optimisation, some problems may have been solved exposing others that now dominate.

In the steps above, I focus on the application related optimisation process, but of course you must ensure the underlying network itself is configured in the most efficient manner to support your application too. Engage the networking specialists in the business and determine if they're able to apply capacity improvements, QoS, network compression, or other techniques to address the problem. Usually, they will not understand your application's needs, so it's important that you're equipped (after the Analyse step) to discuss it with them, and also to make the business case for any costs you're going to be asking them to incur. I've encountered cases where erroneous network configuration caused the applications data to be transmitted over a slow satellite link rather than an overland link, simply because it was using a TCP port that was not "well known" by the networking specialists; obviously rectifying a problem like this can have a dramatic impact on performance, with no software code or configuration changes necessary at all.


If better hardware is an option then definitely go for that. Otherwise

  • Check you are using the best compiler and linker options.
  • If hotspot routine in different library to frequent caller, consider moving or cloning it to the callers module. Eliminates some of the call overhead and may improve cache hits (cf how AIX links strcpy() statically into separately linked shared objects). This could of course decrease cache hits also, which is why one measure.
  • See if there is any possibility of using a specialized version of the hotspot routine. Downside is more than one version to maintain.
  • Look at the assembler. If you think it could be better, consider why the compiler did not figure this out, and how you could help the compiler.
  • Consider: are you really using the best algorithm? Is it the best algorithm for your input size?

Last few % is a very CPU and application dependent thing....

  • cache architectures differ, some chips have on-chip RAM you can map directly, ARM's (sometimes) have a vector unit, SH4's a useful matrix opcode. Is there a GPU - maybe a shader is the way to go. TMS320 's are very sensitive to branches within loops (so separate loops and move conditions outside if possible).

The list goes on.... But these sorts of things really are the last resort...

Build for x86, and run Valgrind /Cachegrind against the code for proper performance profiling. Or Texas Instruments' CCStudio has a sweet profiler. Then you'll really know where to focus...


Not nearly as in depth or complex as previous answers, but here goes: (these are more beginner/intermediate level)

  • obvious: dry
  • run loops backwards so you're always comparing to 0 rather than a variable
  • use bitwise operators whenever you can
  • break repetitive code into modules/functions
  • cache objects
  • local variables have slight performance advantage
  • limit string manipulation as much as possible

The google way is one option "Cache it.. Whenever possible don't touch the disk"


Very difficult to give a generic answer to this question. It really depends on your problem domain and technical implementation. A general technique that is fairly language neutral: Identify code hotspots that cannot be eliminated, and hand-optimize assembler code.


  • आप किस हार्डवेयर पर चल रहे हैं? क्या आप प्लेटफ़ॉर्म-विशिष्ट अनुकूलन (जैसे वेक्टरेशन) का उपयोग कर सकते हैं?
  • क्या आप एक बेहतर संकलक प्राप्त कर सकते हैं? जैसे जीसीसी से इंटेल तक स्विच करें?
  • क्या आप अपना एल्गोरिदम समानांतर में चला सकते हैं?
  • क्या आप डाटा पुनर्गठन करके कैश मिस को कम कर सकते हैं?
  • क्या आप आवेषण अक्षम कर सकते हैं?
  • अपने कंपाइलर और मंच के लिए माइक्रो-ऑप्टिमाइज़ करें। की शैली में, "अगर एक और / तो, सबसे आम कथन पहले रखें"

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




language-agnostic