2013-01-09 29 views
11

हम कुछ अजीब जेवीएम प्रदर्शन मुद्दों का सामना कर रहे हैं।क्यों java.lang.Object.getClass() (और प्रतिबिंब) सामान्य से धीमा है?

हमारे पास एक बड़ा और कुछ हद तक अपारदर्शी जीयूआई घटक (एक्ट्यूएट फॉर्मूला 1 स्प्रेडशीट) है।

अगर हम इसे इवेंट डिस्पैच थ्रेड (जैसा कि आपको करना चाहिए) से प्रारंभ करते हैं, तो हम पाते हैं कि कोड काफी धीरे-धीरे चलता है (माउस को कोशिकाओं का चयन करने के लिए खींचकर, एक ध्यान देने योग्य अंतराल है)।

यदि हम इसे मुख्य लॉन्चर थ्रेड में पहली बार प्रारंभ करते हैं, और केवल तब ही इसे ईडीटी में उपयोग करना शुरू करते हैं, तो यह बहुत तेज़ी से चलता है।

जब मैं क्यों यह धीरे धीरे प्रदर्शन कर रहा है एक प्रोफाइलर का उपयोग कर को देखो, विधि कॉल उस समय के सभी ले रहे हैं:

  • java.lang.Object.getClass()
  • java.lang .reflect.Array.newInstance (कक्षा, पूर्णांक)
  • java.lang.Class.getComponentType()
  • java.lang.Thread.currentThread()

हम विंडोज 7 पर 64-बिट सन हॉटस्पॉट जेवीएम का उपयोग करके (जो जेडीके के साथ आता है)।

क्या किसी को किसी भी कारण से पता है कि उपर्युक्त विधियां सामान्य रूप से इतनी धीमी गति से क्यों हो सकती हैं?

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

मैंने प्रोफाइलर से दो स्क्रीनशॉट संलग्न किए हैं। दोनों में, प्रोफाइलर चल रहा था, जबकि मैंने सब कुछ स्प्रेडशीट कोशिकाओं के चारों ओर माउस खींच लिया था। तो यह सिर्फ जीयूआई घटक अद्यतन कर रहा है और बहुत कुछ नहीं कर रहा है।

पहला "रिलीज लॉक()" नामक विधि में बहुत समय व्यतीत कर रहा है। किसी कारण से, इसमें काफी समय लग रहा है क्योंकि "getComponentType()" सामान्य से अधिक लंबा समय ले रहा है।

releaseLock

के बाद मैंने किया था एक दूसरे के एक "हैक" "releaseLock()" की लागत निकालने के लिए - लेकिन अब यह सिर्फ getClass की वजह से "getLock()" में बहुत समय खर्च करता है() और currentThread() बहुत लंबे समय तक लेने के सामान्य से:

getLock

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

अगर मैं getLock() को अनुकूलित करना चाहता था तो एप्लिकेशन अभी भी धीरे-धीरे अधिक प्रदर्शन करता है। वास्तव में समस्या यह प्रतीत होती है कि getClass() जैसी विधियां बहुत अधिक समय ले रही हैं। इसके लिए क्षतिपूर्ति करने का कोई तरीका नहीं है - getClass() को कई जगहों पर बुलाया जाता है!

प्रदर्शन अंतर प्रोफाइलर के बिना भी ध्यान देने योग्य है।

कृपया यह भी याद रखें कि हम इस कोड में से कोई भी परिवर्तन नहीं कर सकते - यह एक बाहरी घटक है। चुनौती यह बताने के लिए है कि कोड कुछ परिस्थितियों में बनाम धीरे-धीरे क्यों निष्पादित करता है।

+1

क्या आप प्रोफाइलिंग का स्क्रीनशॉट पोस्ट कर सकते हैं? इसके अलावा, प्रोफाइलिंग रनटाइम पर महत्वपूर्ण प्रभाव डाल सकता है। क्या आप उन तरीकों को प्रोफाइलिंग से बाहर कर सकते हैं और देख सकते हैं कि आपके अंतराल के अन्य कारण हैं या नहीं? – jlordo

+0

मुझे नहीं पता कि इन तरीकों को प्रोफाइलिंग से कैसे बाहर निकालना है, लेकिन जैसा कि आप देख सकते हैं कि यह नमूनाकरण का उपयोग कर रहा है, और ब्रेकडाउन दिखा रहा है। मुझे लगता है कि प्रोफाइलर क्या दिखा रहा है वैध है - ऐसा नहीं है कि यह निष्पादित करने वाला एक अलग कोड है, यह बस इतना है कि, किसी कारण से, ये विधि कॉल जो आम तौर पर काफी सस्ती हैं (Object.getClass()) अब काफी समय ले रहे हैं। –

+1

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

उत्तर

1

आप भार के तहत आवेदन के कई मिश्रित (जावा + देशी) jstack -m धागे डंप लेने की कोशिश कर सकते हैं।

यह शायद Object.getClass() के हुड के तहत क्या हो रहा है पर कुछ संकेत देगा।

If profiler is not the answer, what other choices do we have? भी देखें।

What does thread dump looks like when JVM spent time in GC पर भी एक नज़र डालें। सामान्य जेवीएम थ्रेड डंप हमेशा पूर्ण सटीक नहीं हो सकते क्योंकि वे केवल safepoints पर होते हैं।