2009-02-13 13 views
8

मुझे वास्तव में कंपाइलर और जेआईटी ऑप्टिमाइज़ेशन के आंतरिक के बारे में बहुत कुछ पता नहीं है, लेकिन मैं आमतौर पर यह अनुमान लगाने के लिए "सामान्य ज्ञान" का उपयोग करने की कोशिश करता हूं कि अनुकूलित किया जा सकता है और क्या नहीं हो सकता है। तो वहां मैं आज एक साधारण इकाई परीक्षण विधि लिख रहा था:मैं कैसे लिखूं (परीक्षण) कोड जिसे संकलक/जेआईटी द्वारा अनुकूलित नहीं किया जाएगा?

@Test // [Test] in C# 
public void testDefaultConstructor() { 
    new MyObject(); 
} 

यह विधि वास्तव में मुझे चाहिए। यह जांचता है कि डिफ़ॉल्ट कन्स्ट्रक्टर मौजूद है और अपवादों के बिना चलता है।

लेकिन फिर मैंने कंपाइलर/जेआईटी अनुकूलन के प्रभाव के बारे में सोचना शुरू कर दिया। क्या संकलक/JIT new MyObject(); कथन को पूरी तरह से हटाकर इस विधि को अनुकूलित कर सकता है? बेशक, यह निर्धारित करने की आवश्यकता होगी कि कॉल ग्राफ़ के पास अन्य ऑब्जेक्ट्स के साइड इफेक्ट्स नहीं हैं, जो सामान्य कन्स्ट्रक्टर के लिए सामान्य मामला है जो ऑब्जेक्ट की आंतरिक स्थिति को प्रारंभ करता है।

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

फिर भी, मैं सामान्य विषय के बारे में सोचने की कोशिश कर रहा हूं। जब मैंने सोचा कि इस विधि को अनुकूलित करने से कैसे रोकें, मैंने सोचा कि मैं assertTrue(new MyObject().toString() != null) कर सकता हूं, लेकिन यह toString() विधि के वास्तविक कार्यान्वयन पर बहुत निर्भर है, और फिर भी, जेआईटी निर्धारित कर सकता है कि toString() विधि हमेशा एक गैर-शून्य देता है स्ट्रिंग (उदाहरण के लिए यदि वास्तव में Object.toString() कहा जा रहा है), और इस प्रकार पूरी शाखा को अनुकूलित करें। तो इस तरह से काम नहीं करेगा।

मुझे पता है कि सी # में मैं [MethodImpl(MethodImplOptions.NoOptimization)] का उपयोग कर सकता हूं, लेकिन यह वही नहीं है जो मैं वास्तव में देख रहा हूं। मैं यह सुनिश्चित करने के लिए एक (भाषा-स्वतंत्र) तरीका ढूंढने की उम्मीद कर रहा हूं कि इस प्रक्रिया में जेआईटी हस्तक्षेप किए बिना मेरे कोड के कुछ विशिष्ट भाग वास्तव में चलेंगे।

इसके अतिरिक्त, क्या मेरे यूनिट परीक्षण बनाने के दौरान मुझे कोई विशिष्ट ऑप्टिमाइज़ेशन केस पता होना चाहिए?

बहुत बहुत धन्यवाद!

उत्तर

4

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

यदि आपने इसे एक (गलत) द्वारा संरक्षित किया है, जहां झूठा अंतिम है, तो इसे पूरी तरह से सिस्टम से ऑप्टिमाइज़ किया जा सकता है, तो यह पता लगा सकता है कि विधि कुछ भी नहीं करती है और इसे आईटी आउट (ऑप्टिमाइज़) सिद्धांत)।

संपादित करें: वैसे, यह भी बहुत चालाक निर्धारित करने के लिए किया जा सकता है इस विधि कि:

newIfTrue(boolean b) { 
    if(b) 
     new ThisClass(); 
} 
यदि ख गलत है

हमेशा कोई कार्य नहीं करेगा, और अंततः यह पता लगाने कि आपके कोड बी में एक बिंदु पर हमेशा झूठा होता है और इस कोड को पूरी तरह से उस कोड से संकलित करता है।

यह वह जगह है जहां जेआईटी ऐसी चीजें कर सकती है जो किसी भी गैर-प्रबंधित भाषा में लगभग असंभव है।

+0

धन्यवाद। मुझे आश्चर्य है कि जेआईटी इस तरह से क्यों व्यवहार करता है? यदि कोई ऑब्जेक्ट आवंटन बेकार है (जैसा कि वास्तव में कुछ मामलों में स्थिर विश्लेषण द्वारा निर्धारित किया जा सकता है), तो जेआईटी इसे अनुकूलित क्यों नहीं करेगा? –

+0

हालांकि अब मैं एक कोने के मामले के बारे में सोच सकता हूं, लेकिन मुझे लगता है कि यह काफी दुर्लभ है।यदि ऑब्जेक्ट आवंटन उदाहरण के लिए किया गया था ताकि यह सुनिश्चित किया जा सके कि कुछ अन्य ऑब्जेक्ट्स (और यहां तक ​​कि सुनिश्चित करने के लिए कि कोई पेजिंग नहीं होगी) के लिए पर्याप्त मेमोरी उपलब्ध है, तो अनुकूलन धारणा को अमान्य कर देगा। –

+0

जावा मेमोरी मॉडल के अनुसार JVM में प्रोग्राम कोड निष्पादित करने के साथ-साथ एक राज्य में जावा वर्चुअल मशीन (JVM) को छोड़ना आवश्यक है। वास्तव में किसी भी विशिष्ट कोड को निष्पादित करने की आवश्यकता नहीं है या घटना में स्मृति आवंटित करने की आवश्यकता नहीं है कि जेआईटी साबित कर सकता है कि कोड को देखने योग्य प्रोग्राम स्थिति पर कोई प्रभाव नहीं पड़ता है। –

5

मुझे लगता है कि अगर आप इसे अनुकूलित करने के बारे में चिंतित हैं, तो आप थोड़ा अधिक परीक्षण कर सकते हैं।

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

मुझे पता है कि ऐसे लोग हैं जो मुझसे सहमत नहीं हैं, लेकिन मुझे लगता है कि इस तरह की चीज सिर्फ कुछ ऐसी चीज है जो किसी भी उपयोगी कारण के लिए आपके परीक्षणों को दूर कर देगी, यहां तक ​​कि इसे टीडीडी चश्मा के माध्यम से भी देखेगी।

+0

हां, ओवरकिल ftl का परीक्षण। – MichaelGG

+0

मैं आपसे सहमत हूं। जब मैंने इसके बारे में सोचा (आपके उत्तर को पढ़ने के बाद), ऐसे अन्य परीक्षण होने चाहिए जो डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग करते हैं यदि यह परीक्षण अधिक महत्वपूर्ण है कि केवल "संकलित" परीक्षण हो। धन्यवाद! –

+0

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

0

इससे कोई फर्क क्यों पड़ता है? यदि कंपाइलर/जेआईटी स्थिर रूप से निर्धारित कर सकता है कि कोई भी दावा हिट नहीं किया जा रहा है (जो साइड इफेक्ट्स का कारण बन सकता है), तो आप ठीक हैं।

+0

यह भी सत्यापित करने की आवश्यकता है कि कन्स्ट्रक्टर मौजूद है, स्थिर प्रोग्राम स्थिति को प्रभावित नहीं करता है, और JVM द्वारा अनिवार्य रूप से आवश्यक अपवाद फेंक नहीं सकता है जैसे 'NullPointerException'। –

2

इसके बारे में इस तरह सोचें:

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

+0

अच्छा विचार! मैंने इसके बारे में नहीं सोचा था। :) –

1

ऐसा लगता है सी # में मैं यह कर सकता है कि:

[Test] 
public void testDefaultConstructor() { 
    GC.KeepAlive(new MyObject()); 
} 

AFAIU, GC.KeepAlive विधि JIT द्वारा inlined नहीं किया जाएगा, ताकि कोड अपेक्षा के अनुरूप काम करने की गारंटी दी जाएगी। हालांकि, मुझे जावा में एक समान निर्माण नहीं पता है।

+1

-1: भ्रामक। यह वह मामला नहीं है जहां 'जीसी.किपलाइव' की आवश्यकता है (या यहां तक ​​कि कोई भी लाभ भी प्रदान करता है)। –

0

हर आई/ओ एक पक्ष प्रभाव है, तो आप सिर्फ

Object obj = new MyObject(); 
System.out.println(obj.toString()); 

डाल सकते हैं और तुम ठीक हो।

+0

हां, यह निश्चित रूप से ऐसा करने का एक तरीका है। लेकिन यूनिट परीक्षणों में आम तौर पर आउटपुट स्टेटमेंट नहीं होना चाहिए। –

+0

मुझे लगता है कि जब तक आप परीक्षा उत्तीर्ण या विफल हो, यह निर्धारित करने के लिए आप I/O पर भरोसा नहीं कर रहे हैं, तो आप ठीक हैं। –

+1

-1: भ्रामक। वह I/O के बिना ठीक है। यह उत्तर यह दिखता है कि इस फ़ॉर्म के यूनिट परीक्षणों की तरह शुद्धता की गारंटी के लिए I/O की आवश्यकता है। –

2

जेआईटी केवल उन परिचालनों को करने की अनुमति है जो भाषा की गारंटीकृत अर्थशास्त्र को प्रभावित नहीं करते हैं। सैद्धांतिक रूप से, यह आवंटन को हटा सकता है और MyObject कन्स्ट्रक्टर पर कॉल कर सकता है यदि यह गारंटी दे सकता है कि कॉल का कोई दुष्प्रभाव नहीं है और कभी भी अपवाद नहीं फेंक सकता है (OutOfMemoryError की गणना नहीं)।

दूसरे शब्दों में, यदि जेआईटी आपके परीक्षण से कॉल को ऑप्टिमाइज़ करता है, तो आपका परीक्षण को पारित कर दिया होगा।

पुनश्च: ध्यान दें कि यह लागू होता है क्योंकि आप कार्यक्षमता परीक्षण कर रहे हैं के रूप में प्रदर्शन परीक्षण करने का विरोध किया। प्रदर्शन परीक्षण में, यह सुनिश्चित करना महत्वपूर्ण है कि जेआईटी आपके द्वारा मापने वाले ऑपरेशन को अनुकूलित न करे, अन्यथा आपके परिणाम बेकार हो जाएं।

+0

विषय पर बढ़िया दृश्य। एक जोड़ा: कार्यक्षमता के लिए प्रदर्शन परीक्षण का उपयोग करते समय (उदा। जैसे कि सीपीयू के कैश आकार को समझने का प्रयास करना) हमें जेआईटी करने की चाल से बचने के लिए स्पष्ट रूप से '[MethodImpl (MethodImplOptions.NoOptimization)]' जोड़ना चाहिए। –

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

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