2015-11-04 15 views
5

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

जब मैं तर्क के रूप में केवल स्थिरांक के साथ एक स्थिर फ़ंक्शन को कॉल करें, वहाँ एक रास्ता संकलक है कि यह संकलन समय पर पहले से ही कॉल का मूल्यांकन करें और बदलना चाहिए बताने के लिए है परिणाम से कॉल?

उदाहरण:

const double pi = Math.PI; //works as Math.PI is a constant 
const double spi = Math.Sin(Math.PI); //compiler error, because expression must be constant 

कोई निर्देश हैं (बेहतर: गुण) पर स्पष्ट रूप संकलक बताने के लिए कि गणित.पाप की तरह एक स्थिर विधि() को संशोधित नहीं कर रहा है और न ही आंतरिक रूप से किसी भी डाटा पढ़ने, इतना है कि यह था संकलन समय पर कॉल का मूल्यांकन करने के लिए तकनीकी रूप से संभव है?

ओह, और कृपया "const double spi = 0" की तरह जवाब न दें :), क्योंकि मेरा उदाहरण सिर्फ मेरी समस्या का सरलीकृत संस्करण है: अधिकतम प्रदर्शन को बनाए रखते हुए कोड रखरखाव में सुधार करना।

किसी भी मदद के लिए धन्यवाद - यह वास्तव में सराहना की है!

+0

__pure__ समारोह के रूप में एक विधि निर्दिष्ट करने के लिए कोई तरीका नहीं है। कंपाइलर का यह निर्धारित करने का कोई तरीका नहीं है कि Math.Sin() दुष्प्रभाव नहीं करता है या नहीं। – qxg

+0

जहां तक ​​मुझे पता है, नहीं। आप क्या कर सकते हैं परिणामस्वरूप कोड उत्पन्न कर सकते हैं (टी 4 या कस्टम टूल का उपयोग करके), या जेनरेटेड असेंबली को पोस्ट-प्रोसेस करने के लिए आईएल-बुनाई उपकरण का उपयोग करें, या रोज़लिन का उपयोग करके एक अनुकूलित कंपाइलर बनाएं। अगर केवल सी # एक लिस्प थे तो यह इतना कठिन नहीं होगा। ;) –

+0

क्या आप एक * वास्तविक * समस्या को हल करने की कोशिश कर रहे हैं या क्या आप मानते हैं कि सी ++ से संबंधित एक विशिष्ट वाक्यविन्यास यहां आवश्यक है? सी # कॉन्स में मतलब ** कॉन्स **, यानी संकलन के बाद कभी नहीं बदल रहा है। यदि आप एक अपरिवर्तनीय परिणाम चाहते हैं, तो ऐसा करने के लिए * अन्य * तरीके हैं, उदाहरण के लिए एक 'स्थैतिक रीडोनली' मान, या केवल एकमात्र संपत्ति जो स्थिर –

उत्तर

3

संख्यात्मक स्थिरांक के लिए मैं दो विकल्प दिखाई अपनी जेब कैलकुलेटर के साथ गणना करने के लिए और उन स्थिरांक को हार्डकोड:

class MyCalc 
{ 
    // Math.Sin(Math.Pi) 
    private const double spi = 0; 
    // Math.Pi 
    private const double pi = 3.141592653589793; 

    public void Execute() 
    { 
     // .. whatever 
    } 
} 

मुझे यकीन नहीं कर रहा हूँ अगर संकलक पूरी तरह से एक गणना में विकल्प एक दूर का अनुकूलन कर सकते लेकिन यह सबसे पठनीय और mainta होना चाहिए अक्षम रास्ता

यदि आप जितना संभव हो संकलन समय पर अधिक करने की तलाश में हैं, तो चीजें कठिन हो जाती हैं। सी ++ के तहत आपके पास टेम्पलेट्स हैं। मुझे उन्हें लिखने के लिए बोझिल लगता है लेकिन लोगों को इसके साथ amazing things मिलता है। ऐसा लगता है कि compile time functions के साथ यह आसान हो गया है लेकिन मैंने अभी तक कोशिश नहीं की है। डी CTFE है जो वास्तव में शक्तिशाली है। लेकिन डी एक आला है और मैं इसमें कोई गंभीर कोड लिखने से बचूंगा। मुझे काफी स्पष्ट प्रीकंपिलेशन मूल्यांकन के साथ अन्य भाषाओं के बारे में पता नहीं है, लेकिन मुझे यकीन है कि कुछ हैं।

कंपाइलर्स इस दिन स्मार्ट छोड़ दिए गए हैं।संभावनाएं अच्छी हैं कि एक कंपाइलर को बिना किसी संकेत के फ़ंक्शन कॉल को ऑप्टिमाइज़ करने का अवसर दिखाई दे सकता है। डॉटनेट 4.5 के साथ, हमें AggressiveInlining मिल गया है - इसलिए हम संकलक को सही दिशा में मजबूर करने में सक्षम हो सकते हैं। सी/सी ++ में कुछ समान है और problems रहा था। मेरी तरफ से सामान्य सलाह inline से बचना होगा जबतक कि आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं।

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

  1. मत
  2. अभी तक नहीं है (केवल विशेषज्ञों)
+0

अनुकूलन के नियम!+1 – Sweeper

+0

"स्थैतिक रीडोनली फ़ील्ड" विकल्प के लिए एक +1 जो प्रदर्शन के संबंध में सबसे अच्छा कामकाज है। – Reinski

1

[Pure] उन तरीकों के लिए विशेषता है जिनके दुष्प्रभाव नहीं हैं। हालांकि, यह केवल कोड विश्लेषण के लिए प्रयोग किया जाता है, न कि संकलक द्वारा (इस समय)। हालांकि, यह भविष्य में बदल सकता है।

जेटब्रेन रीशेपर एक ही उद्देश्य (कोड विश्लेषण) के लिए समान [Pure] विशेषता प्रदान करता है।

तो, पल के लिए, आप एक मूल्य आप द्वारा पूर्व-गणना की तरह एक वैकल्पिक हल के लिए सबसे अच्छा किसी और के लिए एक टिप्पणी के साथ की जरूरत है, मान के स्रोत पता करने के लिए:

const double spi = 0.0; // Math.Sin(Math.PI) 

या

static readonly double spi = Math.Sin(Math.PI); 

जो निश्चित रूप से रनटाइम के मान की गणना करता है, जिसे आप नहीं चाहते हैं।

विकल्प एक:: स्थिर केवल पढ़ने के लिए (स्टार्टअप पर एक बार गणना) का उपयोग करें:

class MyCalc 
{ 
    private static readonly double spi = Math.Sin(Math.PI); 
    private static readonly double pi = Math.Sin(Math.PI); 

    public void Execute() 
    { 
     // .. whatever 
    } 
} 

विकल्प दो:

+0

शुद्ध-गुण के संदर्भ के लिए एक +1, जो संभावित रूप से भविष्य में उपयोग की जा सकती है ... – Reinski

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