2010-01-29 10 views
26

कृपया इस प्रश्न में कोड पढ़ने योग्यता को अनदेखा करें।क्या सी # कंपाइलर इस कोड को अनुकूलित करने के लिए पर्याप्त स्मार्ट है?

प्रदर्शन के संदर्भ में, निम्नलिखित कोड इस तरह लिखा जाना चाहिए:

int maxResults = criteria.MaxResults; 

if (maxResults > 0) 
{ 
    while (accounts.Count > maxResults) 
     accounts.RemoveAt(maxResults); 
}

या इस तरह:

if (criteria.MaxResults > 0) 
{ 
    while (accounts.Count > criteria.MaxResults) 
     accounts.RemoveAt(criteria.MaxResults); 
}

?

संपादित करें: criteria एक class है, और MaxResults एक सरल पूर्णांक संपत्ति है (यानी, public int MaxResults { get { return _maxResults; } }

एक ब्लैक बॉक्स के रूप में सी # संकलक इलाज MaxResults और यह हर बार का मूल्यांकन करता है या यह स्मार्ट पर्याप्त आंकड़ा है।? बाहर निकलने के लिए मुझे उस संपत्ति के लिए 3 कॉल मिल गई हैं, जिसमें कॉल के बीच उस संपत्ति का कोई संशोधन नहीं हुआ है? क्या होगा यदि MaxResults एक फ़ील्ड था?

अनुकूलन के नियमों में से एक सटीक है, इसलिए मैंने सहजता से इस कोड को लिखा पहली लिस्टिंग, लेकिन मुझे उत्सुकता है कि इस तरह की चीज मेरे लिए की जा रही है स्वचालित रूप से (फिर, कोड पठनीयता को अनदेखा करें)।

(नोट: मुझे 'माइक्रो-ऑप्टिमाइज़ेशन' तर्क सुनने में कोई दिलचस्पी नहीं है, जो कि मैंने पोस्ट किए गए विशिष्ट मामले में मान्य हो सकता है। मुझे कुछ सिद्धांत पसंद है कि क्या हो रहा है या नहीं ।)

+1

आप बाहर के बारे में चिंता क्यों करते हैं? यदि खाते कुछ सरणी या संग्रह हैं, तो गिनती 0 से कम नहीं होगी। और यदि यह कम नहीं है तो 0 जो परवाह करता है कि मैक्सआरसल्ट 0 से कम है या नहीं? (यह अभी भी लूप नहीं होगा) –

+4

@ मैथ्यू: कृपया तर्क पर लटकाओ मत, क्योंकि (ए) यह मेरे आवेदन के लिए सही ढंग से लिखा गया है, और (बी) यह नहीं है कि मैं इस प्रश्न में क्या पूछ रहा हूं। –

+1

खाते। टेक (maxResults) –

उत्तर

58

सबसे पहले, वास्तव में प्रदर्शन प्रश्नों का उत्तर देने का एकमात्र तरीका वास्तव में दोनों तरीकों से प्रयास करना और यथार्थवादी स्थितियों में परिणामों का परीक्षण करना है।

यह कहा गया है कि अन्य उत्तर कहते हैं कि "कंपाइलर" यह अनुकूलन नहीं करता है क्योंकि संपत्ति के साइड इफेक्ट्स सही और गलत दोनों हो सकते हैं। प्रश्न के साथ समस्या (मौलिक समस्या से अलग, जिसे वास्तव में इसका प्रयास करने और परिणाम को मापने के बिना उत्तर नहीं दिया जा सकता है) यह है कि "कंपाइलर" वास्तव में दो कंपाइलर है: सी # कंपाइलर, जो एमएसआईएल और जेआईटी कंपाइलर से संकलित होता है , जो आईएल को मशीन कोड में संकलित करता है।

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

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

चाहे घबराना वास्तव में करता है संपत्ति को इनलाइन करें और फिर मूल्य को अपंजीकृत करें, मुझे कोई जानकारी नहीं है। मैं जिटर के बारे में व्यावहारिक रूप से कुछ भी नहीं जानता। लेकिन अगर ऐसा लगता है तो ऐसा करने की अनुमति है। यदि आप इस बारे में उत्सुक हैं कि यह ऐसा करता है या नहीं, तो आप या तो (1) किसी ऐसे व्यक्ति से पूछ सकते हैं जो जिटर लिखता है, या (2) डीबगर में दिए गए कोड की जांच करें।

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

  • निष्पादन समय

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

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

  • और इसी तरह। यह असली जटिल असली तेजी से मिलता है।

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

+2

+1 मैं इस प्रश्न पर आपका ध्यान आकर्षित करने की उम्मीद कर रहा था। एक महान जवाब के लिए धन्यवाद। –

+1

बिग +1 यह इंगित करने के लिए कि "कंपाइलर" वास्तव में .Net (या जावा, उस मामले के लिए, या किसी अन्य वातावरण में मध्यवर्ती प्रारूप में संकलित नहीं होता है और फिर लागू होता है [JIT लागू हो सकता है)। –

+6

@Eric: आपके उत्तर हमेशा महान होते हैं। इस जवाब के नीचे आपको नाम भी देखे बिना मुझे पता था कि यह आपको होना था। धन्यवाद। नेट और सी # के आंतरिक कार्यों के ब्योरे को साझा करना हम सभी को प्राणियों का सामना करना पड़ेगा। –

7

हैं MaxResults एक संपत्ति तो नहीं, यह अनुकूलित नहीं होगा, क्योंकि गेटर जटिल तर्क हो सकता है, का कहना है:

private int _maxResults; 
public int MaxReuslts { 
    get { return _maxResults++; } 
    set { _maxResults = value; } 
} 

देखें कि किस प्रकार व्यवहार बदल जाएगा अगर यह में लाइनों अपने कोड ?

यदि कोई तर्क नहीं है ... तो आपके द्वारा लिखी गई कोई भी विधि ठीक है, यह एक बहुत ही मिनट का अंतर है और यह कितना पठनीय है आपको (या आपकी टीम) ... आप इसे देख रहे हैं ।

+1

वैसे भी अगर यह एक संपत्ति थी, तो इसे रेखांकित किया जा सकता है लेकिन यह जिट ​​द्वारा किया जाएगा। वह मान किसी अन्य थ्रेड द्वारा भी बदला जा सकता है, इसलिए इसे अनुकूलित करने के लिए सुरक्षित नहीं हो सकता है। –

+0

@ विंज़: धन्यवाद! –

2

इसका परीक्षण क्यों नहीं करें?

बस 2 कंसोल ऐप्स सेट अप करें, इसे 10 मिलियन बार देखें और परिणामों की तुलना करें ... उन्हें ठीक तरह से इंस्टॉल किए गए ऐप्स के रूप में चलाने के लिए याद रखें जो ठीक से स्थापित किए गए हैं या अन्यथा आप यह गारंटी नहीं दे सकते कि आप केवल एमएसआईएल नहीं चला रहे हैं।

वास्तव में आपको शायद 5 उत्तरों प्राप्त होने जा रहे हैं, 'आपको अनुकूलन के बारे में चिंता नहीं करनी चाहिए'। वे स्पष्ट रूप से उन दिनचर्या नहीं लिखते हैं जिन्हें पढ़ने योग्य होने से पहले जितनी जल्दी संभव हो सके (उदाहरण के लिए गेम)।

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

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

+0

उछाल और यकीन है कि मैंने पठनीयता की टिप्पणी की उम्मीद की है ... उसने बोल्ड भी इस्तेमाल किया है; पी –

0

यदि criteria एक वर्ग प्रकार है, तो मुझे संदेह है कि इसे अनुकूलित किया जाएगा, क्योंकि एक और धागा हमेशा उस मूल्य को उस समय बदल सकता है। struct के लिए मुझे यकीन नहीं है, लेकिन मेरी आंत महसूस यह है कि इसे अनुकूलित नहीं किया जाएगा, लेकिन मुझे लगता है कि इससे किसी भी तरह के प्रदर्शन में प्रदर्शन में कोई अंतर नहीं आएगा।

+0

कोई कारण नहीं है कि एक वर्ग को अन्य धागे में एक वर्ग के रूप में संशोधित नहीं किया जा सकता है। structs अपरिवर्तनीय होने की गारंटी नहीं है, और वे संदर्भ द्वारा पारित किया जा सकता है। – Thorarin

+0

यह बहुत सच है। उत्परिवर्तनीय structs इतनी बुराई हैं, मैं कभी उनका उपयोग नहीं करता। इस प्रकार मैं लगभग उस मामले के बारे में भूल गया। तो मेरा आंत महसूस अंततः एक सत्य ज्ञान बन जाता है। ;-) – herzmeister

4

इसे हर बार बुलाया जाएगा और मूल्यांकन किया जाएगा। कंपाइलर का यह निर्धारित करने का कोई तरीका नहीं है कि कोई विधि (या गेटर) निर्धारक और शुद्ध है (कोई दुष्प्रभाव नहीं)।

ध्यान दें कि संपत्ति का वास्तविक मूल्यांकन जेआईटी कंपाइलर द्वारा रेखांकित किया जा सकता है, जो इसे सरल क्षेत्र के रूप में प्रभावी ढंग से तेज़ी से बना सकता है।

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

6

आपके दो कोड नमूने केवल सिंगल थ्रेडेड वातावरण में एक ही परिणाम होने की गारंटी देते हैं, जो नेट नहीं है, और यदि MaxResults एक फ़ील्ड (संपत्ति नहीं है) है। कंपाइलर यह नहीं मान सकता है, जब तक कि आप सिंक्रनाइज़ेशन सुविधाओं का उपयोग नहीं करते हैं, criteria.MaxResults आपके लूप के दौरान नहीं बदलेगा। यदि यह एक संपत्ति है, तो यह नहीं मान सकता कि संपत्ति का उपयोग साइड इफेक्ट्स नहीं है।

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

संबंधित मुद्दे

 संबंधित मुद्दे