2012-06-03 6 views
5

एक सरणी लौटने सेटिंग के दो तरीके/तुलना करें:सेटिंग/लौटने सरणियों के पसंदीदा तरीका

static public float[] test_arr_speeds_1(int a) { 
    return new float[]{ a, a + 1, a + 2, a + 3, a + 4, a + 5, 
         a + 6, a + 7, a + 8, a + 9 }; 
} // or e.g. field = new float... in method 

static public float[] test_arr_speeds_2(int a) { 
    float[] ret = new float[10]; 
    ret[0] = a; 
    ret[1] = a + 1; 
    ret[2] = a + 2; 
    ret[3] = a + 3; 
    ret[4] = a + 4; 
    ret[5] = a + 5; 
    ret[6] = a + 6; 
    ret[7] = a + 7; 
    ret[8] = a + 8; 
    ret[9] = a + 9; 
    return ret; 
} // or e.g. field[0] = ... in method 

दोनों अलग bytecodes पैदा करते हैं और दोनों अपने पूर्व राज्य के लिए decompiled जा सकता है। प्रोफाइलर (100 एम पुनरावृत्तियों, निष्पक्ष, विभिन्न परिवेश) के माध्यम से निष्पादन समय की जांच करने के बाद, _1 विधि का समय लगभग है। 4/3 _2 का समय, भले ही दोनों एक नई सरणी बनाते हैं और दोनों प्रत्येक फ़ील्ड को किसी दिए गए मान पर सेट करते हैं। समय ज्यादातर समय नगण्य हैं, लेकिन यह अभी भी मुझे खराब करता है - _1 स्पष्ट रूप से धीमा क्यों है? क्या कोई उचित, JVM- समर्थित तरीके से मुझे जांच/पुष्टि/समझा सकता है?

+1

संबंधित पोस्टटेकोड प्रस्तुतिकरण यहां पोस्ट करने के लिए पर्याप्त हैं? –

+1

1000 * 1000000 कॉल का औसत समय कम से कम मेरे लिए दोनों विधियों के लिए समान है। – IchBinKeinBaum

+0

प्रिय डाउनवॉटर, क्या आप कृपया यह बता सकते हैं कि यह प्रश्न * कैसे नहीं बल्कि अनुसंधान प्रयोजन दिखाता है और यह कैसे उपयोगी है * अन्य उपयोगकर्ताओं के लिए यह उपयोगी नहीं है, खासकर यदि वोट अन्यथा दिखाए जाते हैं? – vaxquis

उत्तर

6

बाइटकोड (केवल पहले दो आइटमों के लिए) के बीच अंतर है। सबसे पहले विधि:

bipush 10 
newarray float  //creating an array with reference on operand stack 

dup 
iconst_0 
iload_0 
i2f 
fastore    //setting first element 

dup 
iconst_1 
iload_0 
iconst_1 
iadd 
i2f 
fastore    //setting second element 

//... 
areturn    //returning the top of the operand stack 

दूसरी विधि:

bipush 10 
newarray float 
astore_1   //creating an array and storing it in local variable 

aload_1 
iconst_0 
iload_0 
i2f 
fastore    //setting first element 

aload_1 
iconst_1 
iload_0 
iconst_1 
iadd 
i2f 
fastore    //setting second element 

//... 
aload_1 
areturn 

आप देख सकते हैं फर्क सिर्फ इतना है कि सरणी संदर्भ पहले परिदृश्य में संकार्य ढेर पर रखा जाता है (है कि क्यों dup तो कई बार प्रकट होता है - fastore के बाद किसी सरणी के संदर्भ को खोने से बचने के लिए) जबकि दूसरे परिदृश्य में सरणी संदर्भ सामान्य स्टैक पर रखा गया है (जहां विधि तर्क और स्थानीय चर रखा जाता है)। इस परिदृश्य में संदर्भ हर समय पढ़ा जाना चाहिए (aload_1) क्योंकि fastore को ऑपरेंड स्टैक पर सरणी होना आवश्यक है।

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

यदि आप अंतर को माप सकते हैं और आप निम्न स्तर के अनुकूलन कर रहे हैं - तेज़ी से संस्करण चुनें। लेकिन मुझे संदेह है कि अंतर "पोर्टेबल" है (आर्किटेक्चर और जेवीएम संस्करण/कार्यान्वयन के आधार पर आप अलग-अलग समय व्यवहार को पर्यवेक्षक करेंगे)। ऐसा कहा जा रहा है - मैं आपके कंप्यूटर पर तेज़ होने के बजाए अधिक पठनीय संस्करण के लिए जाऊंगा।

+1

भयानक विश्लेषण! – AlexR

+0

यह वही है जो मैं ढूंढ रहा था। दरअसल, अंतर केवल ऑपरेंड/सामान्य स्टैक उपयोग में मौजूद प्रतीत होता है - और मैं मानता हूं कि ज्यादातर समय परेशान करने के लिए यह बहुत कम स्तर है, मैंने बस कारण के बारे में सोचा। मैं भी "अनुकूलित" कोड पर पठनीय कोड पसंद करता हूं। – vaxquis

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