2012-06-19 27 views
10

क्या किसी को पता है कि एक ConcurrentHashMap ("क्लासिकल" हैश मैप की तुलना में) की मेमोरी ओवरहेड क्या है?ConcurrentHashMap मेमोरी ओवरहेड

  • निर्माण पर?
  • किसी तत्व को सम्मिलित करने पर?
+0

यह ConcurrentHashMap की बड़ी संख्या बनाने के लिए दे आप केवल कोर की एक सीमित संख्या है मतलब नहीं है। सीएचएम की एक छोटी संख्या के ऊपरी हिस्से में 1 सेंट से कम स्मृति की संभावना है। –

+0

@ पीटर Lawrey मुझे वास्तव में आपका अंक नहीं मिलता है। "यह बड़ी मात्रा में ConcurrentHashMap बनाने के लिए बेकार है", तो क्या? वे अभी भी एक उपर है। बगल में, भले ही यह स्पष्ट रूप से एक ही समय में कई CHMs के लिए अजीब है, एक आसानी से कल्पना कर सकते हैं कि कम रहने वाले वस्तुओं उनके निर्माण में एक समवर्ती हैश नक्शा बनाने (के एक एक डीबी उन्मुख सॉफ्टवेयर में ऑपरेटर में शामिल होने के मान लीजिए?)। – Maxime

+0

एक कारण आप समवर्ती संग्रह का उपयोग कर सकते हैं क्योंकि आपके पास संग्रह से अधिक कोर हैं। यदि आपके पास कोर की तुलना में कई और संग्रह हैं, तो यह बेहद असंभव है कि आपके पास समवर्ती पहुंच होगी। –

उत्तर

6

यदि आप 64-बिट JVM पर -XX:-UseTLAB -XX:NewSize=900m -mx1g के साथ निम्न चलाते हैं।

public static void main(String... args) throws NoSuchMethodException, IllegalAccessException { 
    for (int i = 0; i < 4; i++) { 
     long used1 = usedMemory(); 
     populate(new HashMap()); 
     long used2 = usedMemory(); 
     populate(new ConcurrentHashMap()); 
     long used3 = usedMemory(); 
     System.out.println("The ratio of used memory is " + (double) (used3 - used2)/(used2 - used1)); 
     System.out.println("For an extra " + ((used3 - used2) - (used2 - used1))/1000000 + " bytes per entry was used."); 
    } 
} 

private static void populate(Map map) { 
    for (Integer i = 0; i < 1000000; i++) 
     map.put(i, i); 
} 

private static long usedMemory() { 
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
} 

आपको एक मिलियन प्रविष्टियों के लिए जावा 6 और 7 के साथ मिलता है।

The ratio of used memory is 1.1291128466982379 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 

मेमोरी की आठ एमबी लगभग 5 सेंट की लागत।

+0

स्मृति उपयोग का माप कितना विश्वसनीय है? – assylias

+0

क्या आप थ्रेड स्थानीय आवंटन का उपयोग करने के बिंदु को समझा सकते हैं? धन्यवाद! – assylias

+0

यह हॉटस्पॉट या ओपनजेडीके की तुलना में जावा 5 या अन्य जेवीएम पर अलग हो सकता है लेकिन अगर यह काफी अलग है तो मुझे आश्चर्य होगा। 32-बिट जेवीएम पर अंतर छोटा हो सकता है। –

2

मैं वास्तव में प्रश्न के आधार को समझ नहीं पा रहा हूं - या तो आपको सहमति की आवश्यकता है या आप नहीं करते हैं।

हालांकि, this link के अनुसार, खाली ConcurrentHashMap की स्मृति पदचिह्न 1700 बाइट्स है। यह अनुशंसा करता है कि आप ConcurrentHashMap का उपयोग करें यदि आपके पास एकाधिक धागे हैं जिन्हें पढ़ने/लिखने की आवश्यकता है, लेकिन Hashtable यदि आपके पास कई थ्रेड हैं जिन्हें पढ़ने की आवश्यकता है लेकिन एक लिखने की आवश्यकता है।

+0

लिंक प्रासंगिक होने के लिए बहुत पुराना तरीका है। दरअसल, यह आलेख जावा 7 से पहले प्रकाशित हुआ था (04/28/2012) और कार्यान्वयन शायद बदल गया है। इसके अलावा, आपका जवाब अधूरा है क्योंकि मैं भी सम्मिलन के लिए पूछता हूं (क्या कोई है)। – Maxime

+2

@ मैक्सिम कार्यान्वयन शायद इतना नहीं बदला है, लेकिन किसी भी मामले में यह डेटा खोजने के लिए उपयोग की जाने वाली विधि का वर्णन करता है। कुछ शोध से पता चलता है कि किसी और ने अभी तक इसे नहीं किया है। – purtip31

4

ConcurrentHashMap निर्माण और सम्मिलन दोनों में HashMap की तुलना में काफी अधिक स्मृति का उपयोग नहीं करता है।

intialization

ConcurrentHashMap पर एक HashMap के रूप में स्मृति के लगभग एक ही राशि का उपयोग करता है, अतिरिक्त किताब रखने चर और ताले की जोड़ी के लिए थोड़ा और अधिक हो सकता है।

प्रारंभ के दौरान, ConcurrentHashMap कुंजी-मानों को स्टोर करने के लिए 16 सेगमेंट बनाता है, प्रत्येक सेगमेंट हैश मैप के बराबर है।

प्रत्येक सेगमेंट की आंतरिक क्षमता/आकार कुल आरंभिक क्षमता का 1/16 है। तो संक्षेप में, ConcurrentHashMap एक हैश मैप के बराबर 16 छोटे हैश मैप्स बनाता है। प्रत्येक सेगमेंट में अपने लॉक और बुक-रखरखाव चर (गिनती, थ्रेसहोल्ड इत्यादि) के जोड़े हैं, यह अतिरिक्त मेमोरी ओवरहेड है।

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

स्मृति में यह छोटा ओवरहेड एक डेवलपर समेकन के बदले में स्वीकार करने के इच्छुक है।

निवेशन

जब सेगमेंट भरा हो पर, उस सेगमेंट के आकार में वृद्धि की जाएगी। आकार बढ़ाने की नीति हैश मैप के समान है। loadfactor पैरामीटर सेगमेंट के आकार को बढ़ाने का निर्णय लेता है। ध्यान दें कि भरने वाले सेगमेंट में वृद्धि होगी।एक बार फिर, मेमोरी ओवरहेड हैश मैप के समान ही है।

कुल मिलाकर, ConcurrentHashMapHashMap की तुलना में काफी अधिक स्मृति का उपयोग नहीं करता है, लेकिन इसकी वास्तव में कड़ी मेहनत प्रत्येक और ConcurrentHashMap द्वारा प्रयोग किया जाता हर अतिरिक्त बाइट को मापने के लिए।