2010-06-26 27 views
5

मैं अपने multihreaded -agentlib:hprof=cpu=samples का उपयोग कर कार्यक्रम बेंचमार्क किया गया है और परिणामों में निम्न पंक्ति आश्चर्य हुआ:जावा रूपरेखा: java.lang.Object.hashCode CPU समय के आधे लेता है, लेकिन कभी explictly बुलाया

rank self accum count trace method 
    1 52.88% 52.88% 8486 300050 java.lang.Object.hashCode 

मैं अपने प्रोग्राम में कभी भी हैशकोड() को स्पष्ट रूप से कॉल नहीं करता हूं। इसका कारण क्या हो सकता है? मैं इस समय "अपशिष्ट" के स्रोत को कैसे समझ सकता हूं और यह सामान्य है या नहीं?

धन्यवाद, डेविड

+1

यह अच्छा होगा अगर आपको यह समझाया जाए कि यह पहली जगह क्यों है। –

उत्तर

5

सबसे अधिक संभावना तुम बहुत गहराई में इस तरह के एक HashMap के रूप में एक मानचित्र का उपयोग कर रहे हैं।

हैश मैप ने वस्तुओं को वितरित करने के लिए hashCode का उपयोग किया। यदि आप इस डेटा संरचना के साथ कई ऑब्जेक्ट्स का उपयोग कर रहे हैं, तो आपके .equals बहुत महत्वपूर्ण हैं और आपकी .hashCode विधि ठीक से कार्यान्वित की गई है।

देखें: प्रभावी जावा मद 8: Always override hashCode when you override equals

+0

धन्यवाद! आप शायद सही हो। मैं वास्तव में यादृच्छिक अभिगम क्षमताओं के उपयोग को छोड़ सकता हूं (यह है कि आप इसे कैसे कहते हैं?), और मुझे वस्तुओं के क्रम की परवाह नहीं है। मुझे बस ऑब्जेक्ट्स जोड़ने में सक्षम होने की आवश्यकता है, फिर उन सभी पर पुन: प्रयास करें। साथ ही, यह वास्तव में एक सेट है (मुझे एक ही ऑब्जेक्ट को एक से अधिक बार नहीं चाहिए), लेकिन मैं इसे कभी भी एक से अधिक बार जोड़ने का प्रयास नहीं करूंगा ... क्या मुझे इसके बजाय एक सूची का उपयोग करना चाहिए (हालांकि मुझे परवाह नहीं है आदेश के बारे में)? इस तरह के सेट के लिए सबसे कुशल डेटा संरचना क्या है? –

+0

यह एक हैशसेट भी हो सकता है ... –

+0

यह वास्तव में हैशसेट है। अब मैं सभी को ArrayLists में परिवर्तित कर दिया। अब यह लाइन प्रोफाइलर से गायब हो जाती है लेकिन कुल रन टाइम बहुत समान बना रहा। अजीब। है न?! –

0

आप mot शायद सही कर रहे हैं। मैं वास्तव में यादृच्छिक अभिगम क्षमताओं के उपयोग को छोड़ सकता हूं (यह है कि आप इसे कैसे कहते हैं?), और मुझे वस्तुओं के क्रम की परवाह नहीं है। मुझे बस ऑब्जेक्ट्स जोड़ने में सक्षम होने की आवश्यकता है, फिर उन सभी पर पुन: प्रयास करें। साथ ही, यह वास्तव में एक सेट है (मुझे एक ही ऑब्जेक्ट को एक से अधिक बार नहीं चाहिए), लेकिन मैं इसे कभी भी एक से अधिक बार जोड़ने का प्रयास नहीं करूंगा ... क्या मुझे इसकी बजाय सूची का उपयोग करना चाहिए (हालांकि मुझे इसकी परवाह नहीं है आदेश)? इस तरह के सेट के लिए सबसे कुशल डेटा संरचना क्या है?

ए हैशसेट को हैश मैप के रूप में लागू किया गया है जो स्वयं की कुंजी को मैप करता है, इसलिए हैशसेट पर स्विच करने से प्रदर्शन में कोई फर्क नहीं पड़ता है।

अन्य विकल्प एक ट्रीसेट हैं, या (यह मानते हुए कि आपका एप्लिकेशन सूची वर्गों में से एक को डुप्लिकेट डालने का प्रयास नहीं करेगा)। यदि आपका आवेदन ऐसा है कि एक सूची काम करेगी, तो एक ऐरेलिस्ट या लिंक्डलिस्ट एक हैशसेट या ट्रीसेट से अधिक कुशल होगी।

हालांकि, hashCode विधियों में आपके आवेदन का 50% समय व्यय करने के बारे में कुछ बहुत ही ख़राब है। जब तक हैश टेबल का आकार बदल नहीं जाता है, तब तक हैशकोड विधि को प्रति सेट या मानचित्र ऑपरेशन के दौरान ही बुलाया जाना चाहिए। तो या तो बहुत सारे मानचित्र/सेट आकार बदल रहे हैं, या आप बड़ी संख्या में सेट add संचालन कर रहे हैं।

है nextInt() वास्तव में महंगा (AFAIK, वस्तु hashCode विधि सस्ती है, इसलिए प्रत्येक कॉल की लागत एक मुद्दा नहीं होना चाहिए।)

संपादित करें? कोई विकल्प?

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

+0

वास्तव में कई जोड़ों को जोड़ते हैं। जैसा कि बताया गया है, मैंने ArrayList पर स्विच किया लेकिन कुल समय में थोड़ा सुधार हुआ। अब, शीर्ष रैंकिंग सीपीयू टाइम उपभोक्ता है: रैंक स्वयं accum गिनती ट्रेस विधि 1 19.30% 19.30% 2727 300122 java.util.Random.next मैं वास्तव में 0 और ~ 10 के बीच पूर्णांक प्राप्त करने के लिए rand.nextInt() को कॉल करता हूं^7। अगला है() वास्तव में महंगा है? कोई विकल्प? –

1

एक चीज जो आपको करना चाहिए वह यह देखने के लिए मिलान करने वाले स्टैक ट्रेस को देखना है कि इसे कौन कॉल कर रहा है; परिवर्तन वास्तव में हैश मैप है।

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

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

  • कोई संबंधित समस्या नहीं^_^