क्या कम विलंबता कोड कभी-कभी "बदसूरत" होना पड़ता है?


21

(यह मुख्य रूप से उन लोगों के उद्देश्य से है, जिनके पास कम विलंबता प्रणालियों का विशिष्ट ज्ञान है, लोगों को सिर्फ बेबाक राय के साथ जवाब देने से बचने के लिए)।

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

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

मुझे ऐसे क्षेत्रों में काम करने वाले लोगों से सुनने में दिलचस्पी होगी।


1
@ user997112: करीबी कारण स्वयं व्याख्यात्मक है। यह कहता है: "हम तथ्यों, संदर्भों या विशिष्ट विशेषज्ञता द्वारा समर्थित उत्तर की उम्मीद करते हैं, लेकिन इस प्रश्न की संभावना वाद-विवाद, बहस, मतदान या विस्तारित चर्चा होगी। जरूरी नहीं कि वे सही हों, लेकिन इसका मतलब यह नहीं था। कारण सभी तीन करीबी मतदाताओं द्वारा चुना गया।
रॉबर्ट हार्वे

अनायास, मैं कहूंगा कि यह सवाल करीबी वोटों को आकर्षित करने का कारण है कि इसे पतले-पतले रेंट के रूप में माना जा सकता है (हालांकि मुझे नहीं लगता कि यह है)।
रॉबर्ट हार्वे

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

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

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

जवाबों:


31

क्या आपको लगता है कि "अच्छा" ऑब्जेक्ट ओरिएंटेड कोड लिखने और बहुत [sic] कम विलंबता कोड लिखने के बीच एक व्यापार-बंद है?

हाँ।

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

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


15
"इसे काम करो, फिर इसे जल्दी करो"। जैसा कि मैंने सवाल पढ़ा, यह उत्तर मेरे द्वारा कहे गए सब कुछ को बहुत कवर करता है।
कार्सन 63000

13
मैं "उपाय
जोड़ूंगा

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

1
"समय से पहले अनुकूलन" पर - यह तब भी लागू होता है, भले ही अनुकूलित कोड बिना अडॉप्ट किए गए कोड के समान "अच्छा" हो। बिंदु गति / जो भी आप को प्राप्त करने की आवश्यकता नहीं है के लिए लक्ष्य समय बर्बाद नहीं है। वास्तव में अनुकूलन हमेशा गति के बारे में नहीं होता है, और यकीनन "सौंदर्य" के लिए अनावश्यक अनुकूलन जैसी कोई चीज होती है। आपके कोड को पठनीय और बनाए रखने के लिए कला के महान कार्यों की आवश्यकता नहीं है।
स्टीव

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

5

हां, मैं जो उदाहरण देता हूं वह C ++ बनाम जावा नहीं है, बल्कि असेंबली बनाम COBOL है क्योंकि यह वही है जो मैं जानता हूं।

दोनों भाषाएं बहुत तेज हैं, लेकिन, यहां तक ​​कि जब भी संकलित किया जाता है, तो कई और निर्देश होते हैं जो निर्देश सेट में रखे जाते हैं कि जरूरी नहीं कि उन निर्देशों को विधानसभा में स्वयं लिखना हो।

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

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


3

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

व्यापार बंद व्यापार लागत से आता है। अधिक जटिल कोड को और अधिक कुशल प्रोग्रामर की आवश्यकता होती है (और अधिक ध्यान केंद्रित कौशल सेट के साथ प्रोग्रामर, जैसे कि सीपीयू वास्तुकला और डिजाइन ज्ञान वाले), कोड को पढ़ने और समझने और कीड़े को ठीक करने में अधिक समय लगता है। इस तरह के कोड को विकसित करने और बनाए रखने की व्यावसायिक लागत सामान्य रूप से लिखे गए कोड से 10x - 100x की सीमा में हो सकती है।

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

कुछ गति अनुकूलन अन्य की तुलना में बेहतर रिटर्न-ऑन-इन्वेस्टमेंट (आरओआई) बनाते हैं। सामान्यतः, कुछ अनुकूलन तकनीकों को सामान्य रूप से लिखे गए कोड की तुलना में कोड में स्थिरता (उच्च-स्तरीय संरचना और निचले स्तर की पठनीयता को संरक्षित करने) पर कम प्रभाव के साथ लागू किया जा सकता है।

इस प्रकार, एक व्यवसाय स्वामी को चाहिए:

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

ये ट्रेड-ऑफ परिस्थितियों के लिए अत्यधिक विशिष्ट हैं।

प्रबंधकों और उत्पाद स्वामियों की भागीदारी के बिना ये जानबूझकर तय नहीं किए जा सकते।

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


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

जिन तकनीकों के साथ मेरा कुछ एक्सपोज़र है, वे हैं: (किसी भी स्तर की विशेषज्ञता का दावा करने की कोशिश किए बिना) शॉर्ट-वेक्टर ऑप्टिमाइज़ेशन (SIMD), फाइन-ग्रेन्ड टास्क समानता, मेमोरी प्री-एलोकेशन और ऑब्जेक्ट रीयूज़।

SIMD का आमतौर पर निम्न-स्तर की पठनीयता पर गंभीर प्रभाव पड़ता है, भले ही इसके लिए आमतौर पर उच्च-स्तरीय संरचनात्मक परिवर्तनों की आवश्यकता नहीं होती है (बशर्ते कि एपीआई को अड़चन-रोकथाम को ध्यान में रखकर बनाया गया हो)।

कुछ एल्गोरिदम को आसानी से SIMD में परिवर्तित किया जा सकता है (embarassingly- वेक्टर करने योग्य)। SIMD का उपयोग करने के लिए कुछ एल्गोरिदम को अधिक कम्प्यूटेशन पुनर्व्यवस्था की आवश्यकता होती है। वेवफ्रंट SIMD समानता जैसे चरम मामलों में, लाभ लेने के लिए पूरी तरह से नए एल्गोरिदम (और पेटेंट कार्यान्वयन) को लिखा जाना चाहिए।

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

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

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


नहीं, वस्तु-उन्मुखता के साथ विरोधाभास में फास्ट कोड की आवश्यकता नहीं है।

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

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

ऑब्जेक्ट-ओरिएंटेड डिज़ाइन (OOD) के अधिकांश लाभ खो गए हैं। सबसे महत्वपूर्ण बात यह है कि निम्न-स्तर के डिजाइन में कोई सहजता नहीं है। एक साथी प्रोग्रामर यह नहीं सीख सकता है कि पहली बार पूरी तरह से समझने के बिना निचले स्तर के कोड के साथ कैसे काम किया जाए कि एल्गोरिथ्म को पहले स्थान पर कैसे रूपांतरित और विघटित किया गया था, और यह समझ परिणामी कोड से प्राप्य नहीं है।


2

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

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


2

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

आवश्यकता पड़ने पर लूप अनरोलिंग जैसी अन्य अनुकूलन को स्वच्छ फैशन में जोड़ा जा सकता है।

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

मैंने पाया है कि जिस कोड को मैंने ऑप्टिमाइज़ किया है उस पर 80/20 का नियम लागू होता है। अंगूठे के एक नियम के रूप में मैं ऐसी किसी भी चीज़ का अनुकूलन नहीं करता जो कम से कम 80% समय नहीं ले रही है। मैं तब 10 गुना प्रदर्शन वृद्धि के लिए लक्ष्य (और आमतौर पर प्राप्त) करता हूं। यह 4 गुना के बारे में प्रदर्शन में सुधार करता है। मेरे द्वारा लागू किए गए अधिकांश अनुकूलन ने कोड को "सुंदर" कम नहीं बनाया है। आपकी माइलेज भिन्न हो सकती है।


2

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

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

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


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

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

1

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

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


1

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

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

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

सटीक उपकरण है कि कैश मिसेज और शाखा गलतफहमी की तरह मैट्रिक्स प्रदान कर सकते हैं के साथ मापने क्या क्षेत्र में विशेषज्ञता के किसी भी स्तर के सभी लोगों को जांच में रखता है।

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

प्रदर्शन के लिए डिजाइनिंग

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

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

मोटे इंटरफ़ेस डिजाइन

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

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

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

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

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

मेमोरी पूल

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

यह विचार महँगी चीज़ों को धकेलने के समान है (एक सामान्य प्रयोजन के आवंटन के खिलाफ एक मेमोरी चंक आवंटित करना, जैसे) एक मोटे और मोटे स्तर पर। एक मेमोरी पूल को बल्क में मेमोरी से निपटने के लिए डिज़ाइन किया गया है ।

टाइप सिस्टम अलग मेमोरी

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

C ++ में एक सामान्य उदाहरण उन मामलों के लिए होगा जहां बहुरूपता की आवश्यकता होती है, जहां प्राकृतिक प्रलोभन एक सामान्य प्रयोजन स्मृति आवंटनकर्ता के खिलाफ एक उपवर्ग के प्रत्येक उदाहरण को आवंटित करना है।

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

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

जावा जैसी भाषाओं में, जब यह संभव हो int, तो इसके बजाय टेंकलेंकी क्षेत्रों (तंग छोरों में संसाधित क्षेत्र) (जैसे अभी भी भारी उच्च-स्तरीय इंटरफ़ेस के पीछे ) के लिए सादे पुराने डेटा प्रकारों के अधिक सरणियों का उपयोग करने में मदद मिल सकती है, , ArrayListउपयोगकर्ता परिभाषित Integerवस्तुओं की। यह स्मृति अलगाव से बचा जाता है जो आम तौर पर उत्तरार्द्ध के साथ होता है। C ++ में, हमें संरचना को बहुत अधिक नीचा नहीं दिखाना है यदि हमारी मेमोरी आवंटन पैटर्न कुशल हैं, क्योंकि उपयोगकर्ता-परिभाषित प्रकारों को वहां और यहां तक ​​कि एक सामान्य कंटेनर के संदर्भ में भी आवंटित किया जा सकता है।

फ्यूज़िंग मेमोरी बैक टुगेदर

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

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

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

कुरूप

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

खतरनाक

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

सुंदरता

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

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

टी एल; डॉ

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


0

अलग होने के लिए नहीं, लेकिन यहाँ मैं क्या करूँ:

  1. इसे साफ और रखरखाव योग्य लिखें।

  2. क्या प्रदर्शन निदान , और समस्याओं यह आपको बताता है, न लोगों को आप अनुमान लगा दें। गारंटी है, वे आपकी अपेक्षा से अलग होंगे।

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

तो क्या एक व्यापार है? मैं वास्तव में ऐसा नहीं सोचता।


0

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


0

एंड-यूज़र के लिए क्या मायने रखता है?

  • प्रदर्शन
  • सुविधाएँ / कार्यशीलता
  • डिज़ाइन

केस 1: खराब कोड का अनुकूलन

  • कठिन रखरखाव
  • शायद ही पठनीय हो अगर एक ओपन-सोर्स प्रोजेक्ट के रूप में

केस 2: गैर-अनुकूलित अच्छा कोड

  • आसान रखरखाव
  • उपयोगकर्ता का बुरा अनुभव

समाधान?

आसान, कोड के प्रदर्शन महत्वपूर्ण टुकड़ों का अनुकूलन

उदाहरण के लिए:

एक प्रोग्राम जिसमें 5 तरीके होते हैं , उनमें से 3 डेटा मैनेजमेंट के लिए होते हैं, 1 डिस्क रीडिंग के लिए, दूसरा डिस्क राइटिंग के लिए

ये 3 डेटा प्रबंधन विधियाँ दो I / O विधियों का उपयोग करती हैं और उन पर निर्भर करती हैं

हम I / O विधियों का अनुकूलन करेंगे।

कारण: I / O विधियों को बदलने की संभावना कम है, न ही वे ऐप के डिज़ाइन को प्रभावित करते हैं, और सभी में, उस कार्यक्रम में सब कुछ उन पर निर्भर करता है, और इस तरह वे प्रदर्शन महत्वपूर्ण लगते हैं, हम उन्हें अनुकूलित करने के लिए जो भी कोड का उपयोग करेंगे। ।

इसका अर्थ है कि हमें कोड के कुछ भागों का अनुकूलन करके इसे तेजी से रखते हुए कार्यक्रम का अच्छा कोड और प्रबंधनीय डिजाइन प्राप्त होता है

में सोच रहा हूँ..

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.