5

मैं ऑब्जेक्ट आवंटन के संबंध में कुछ प्रदर्शन परीक्षण कर रहा था, जब मैं एक अजीब परिणाम में आया था।जावा: फ़ंक्शन को बार-बार कॉल करते समय प्रदर्शन में वृद्धि का कारण क्या होता है?

public static long TestMethod(){ 
    int len = 10000000; 
    Object[] obs = new Object[len]; 
    long t = System.nanoTime(); 
    for (int i = 0; i < len; i++) { 
     obs[i] = new Object(); 
    } 
    return System.nanoTime() - t; 
} 

public static void main(String... args) throws InterruptedException { 
    for(int i = 0; i < 10; i++){ 
     System.gc(); 
     System.gc();//Wait for the gc to be finished 
     Thread.sleep(1000); 
     System.out.println(TestMethod()); 
    } 
} 

उम्मीद: मैं निम्नलिखित जावा कोड है सबसे पहले कॉल की वजह से ऑपरेटिंग सिस्टम और हॉटस्पॉट संवर्द्धन से एक बड़ा स्मृति स्थान का अनुरोध करने के लिए तो दूसरी कॉल धीमी हो जाएगा। लेकिन दूसरा और तीसरा लगभग समान होगा।

अवलोकन किया गया परिणाम:

11284734000 
799837000 
682304000 
304736000 
380770000 
392786000 
374279000 
381611000 
379174000 
407256000 

फिर भी तीसरे और चौथे चरण के बीच एक काफी गति को। इस गति का कारण क्या है? मैं कैसे सुनिश्चित कर सकता हूं कि अन्य कार्यों का परीक्षण करते समय मेरे माप सटीक हैं, क्या मुझे मापने से पहले चार गुना अधिक फ़ंक्शन को कॉल करना होगा?

+0

[जस्ट-इन-टाइम संकलक स्टार्टअप देरी] (http://en.wikipedia.org/wiki/Just-in-time_compilation#Startup_delay_and_optimizations) –

+1

दिलचस्प पढ़ने: http://stackoverflow.com/questions/504103/कैसे-करें-मैं-लिखने-एक-सही-माइक्रो-बेंचमार्क-इन-जावा - विशेष रूप से, '-XX: + प्रिंटकंपिलेशन -verbose के साथ चल रहा है: जीसी' वीएम पैरामीटर आपको यह समझने में मदद करेगा कि क्या हो रहा है। – assylias

+0

@ वासिलियास: दिलचस्प। उन पैरामीटर को नहीं पता था। ऐसा लगता है कि यह दूसरी कॉल में फ़ंक्शन को दोबारा जोड़ रहा है, और पहले तीन कॉल में 2 कचरा संग्रह कर रहा है, और अंतिम कॉल फ़ंक्शन कॉल में कोई कचरा संग्रह नहीं कर रहा है। – user23127

उत्तर

4

इस गति का कारण क्या है?

यह जेआईटी संकलन की सबसे अधिक संभावना है, लेकिन यह कोड लोडिंग और/या गर्म प्रभावों को ढेर से भी योगदान दे सकता है।

मैं कैसे सुनिश्चित कर सकता हूं कि अन्य कार्यों का परीक्षण करते समय मेरे माप सटीक हैं, क्या मुझे मापने से पहले चार गुना अधिक फ़ंक्शन को कॉल करना होगा?

आपको ऐसा कुछ करने की ज़रूरत है। आपके माप से जेवीएम वार्मअप प्रभाव को खत्म करने का कोई और तरीका नहीं है, और अभी भी प्रतिनिधि परिणाम प्राप्त करें। जावा के लिए वैध "माइक्रो-बेंचमार्क" लिखना मुश्किल है, और आपको प्रयास करने से पहले सभी मुद्दों पर पढ़ने की आवश्यकता है। इस से शुरू करें: How do I write a correct micro-benchmark in Java?


मैं भी अन्य चीजों की एक जोड़ी ध्यान दें होगा:

  1. अपने माप से कचरा संग्रहण की लागत निकालने के लिए आपका प्रयास (मैं मान लेते हैं कि क्या आप होने लगते हैं जा रहा है) विफल होने के लिए दिखाई देते हैं। ऐसा लगता है कि आपको testMethod के निष्पादन के दौरान मामूली संग्रह मिल रहे हैं।यह आपके "स्थिर स्थिति" परिणामों में ~ 7% परिवर्तनशीलता के लिए जिम्मेदार होगा।

  2. किसी ऑब्जेक्ट को मुक्त करने की लागत से आवंटित करने की लागत को अलग करने से यह आपको भ्रामक परिणाम देने की संभावना है। ऑब्जेक्ट आवंटित करने की "कुल" लागत में रीसाइक्लिंग होने पर स्मृति को शून्य करने की लागत शामिल होती है ... और यह कचरा कलेक्टर द्वारा किया जाता है।

  3. वास्तव में, सबसे उपयोगी उपाय एक आवंटित/एकत्रित चक्र के प्रति-वस्तु लागत प्रति वस्तु है। और वह (आश्चर्यजनक रूप से) जीसी चलाते समय गैर-कचरे की मात्रा पर निर्भर करता है ... जो कुछ है जो आपका बेंचमार्क ध्यान में नहीं रखता है।

2

, कई कारकों है कि समारोह के निष्पादन में तेजी लाने सकता है कर रहे हैं के रूप में आप ने कहा:

  • सभी JIT के सबसे अपने आवेदन के दौरान विभिन्न deegrees या पल में हो सकता है (इस दिए बिना क्यों रूपरेखा है JVM गरम के लिए पर्याप्त समय के परिणाम भ्रामक)
  • ओएस
  • वस्तुओं के लिए ढेर पर स्मृति का पुन: उपयोग करने के लिए स्मृति के अनुरोध को जन्म दे सकता है कि आप
आवंटन कर रहे हैं

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

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