2010-05-19 10 views
7

मैं एक bespoke तार प्रोटोकॉल का उपयोग कर टीसीपी पर भेजे गए संदेशों को संसाधित करने के लिए कोडेक लिख रहा हूं। डीकोड प्रक्रिया के दौरान मैं String एस, BigDecimal एस और तिथियों की संख्या बना देता हूं। क्लाइंट-सर्वर का उपयोग पैटर्न मतलब है कि यह आम है ग्राहक एक अनुरोध जारी करने के लिए और फिर आदि प्रतिक्रिया संदेशों के हजारों है, जो की एक बड़ी संख्या में जो परिणाम नकलString रों, BigDecimal रों,पर्मजेन स्पेस या रोल-माय-इंटर्न इंटर्न विधि का प्रयोग करें?

डिकोड इसलिए मैं के लिए ने InternPool<T> वर्ग बनाया है जो मुझे ऑब्जेक्ट के प्रत्येक वर्ग को प्रशिक्षित करने की इजाजत देता है। आंतरिक रूप से, पूल WeakHashMap<T, WeakReference<T>> का उपयोग करता है।

InternPool<BigDecimal> pool = new InternPool<BigDecimal>(); 

... 

// Read BigDecimal from in buffer and then intern. 
BigDecimal quantity = pool.intern(readBigDecimal(in)); 

मेरा प्रश्न: उदाहरण के लिए: मैं BigDecimal के लिए InternPool उपयोग कर रहा हूँ लेकिन मैं यह भी बजाय StringString के intern() विधि के लिए उपयोग करने पर विचार करना चाहिए, जो मेरा मानना ​​है कि PermGen स्थान का उपयोग करता? PermGen अंतरिक्ष का उपयोग करने का क्या फायदा है?

+1

@kts: [] BigDecimal के लिए अगर मैं बाइट मैप करने के लिए थे समस्या तो यह है कि बाइट [] कुछ भी द्वारा संदर्भित नहीं किया जाएगा एक बार प्रशिक्षु पूल बनाया गया है/BigDecimal लौट आए। बाइट मानना ​​[] अंतर्निहित WeakHashMap में कुंजी है इससे संबंधित बिगडिसीमल उपयोग में होने के बावजूद प्रवेश को हटा दिया जाएगा। – Adamski

+1

क्या 'वीक रेफरेंस' इसके लिए उपयुक्त है, या आप 'सॉफ्ट रेफरेंस' का उपयोग कर रहे हैं? जीसी दोनों के लिए अलग-अलग व्यवहार करता है और ऐसा लगता है जैसे आप एक प्रकार का कैश बनाने की कोशिश कर रहे हैं; उस उद्देश्य के लिए कमजोर संदर्भ अच्छे उपयोग नहीं हैं। http://stackoverflow.com/questions/2861410/weakhashmap-iteration-and-garbage-collection/2862174#2862174 –

+0

@Adamski मैं केवल BigDecimal पर एक SoftReference और करने के लिए एक ReferenceQueue का प्रयोग करेंगे: क्यों कुछ कारणों के लिए यहाँ मेरा उत्तर देखें बिगडिसीमल को एक बार दबाए जाने के बाद मानचित्र से 'बाइट [] 's हटा दें। (शायद एक BiMap की आवश्यकता है)।यह अनावश्यक BigDecimal वस्तुओं के निर्माण को खत्म कर सकता है स्मृति/जीसी रनटाइम और निष्पादन समय (केवल एक बार निर्माण करना है) की बचत। – KitsuneYMG

उत्तर

2

ऐसा नहीं है कि JVM के String.intern() पूल तेजी से हो जाएगा संभव है। AFAIK, यह मूल कोड में कार्यान्वित किया जाता है, तो सिद्धांत रूप में यह तेजी से हो सकता है और WeakHashMap और WeakReference का उपयोग कर एक पूल कार्यान्वित की तुलना में कम जगह का उपयोग करना चाहिए। इसकी पुष्टि करने के लिए आपको कुछ सावधानीपूर्वक बेंचमार्किंग करने की आवश्यकता होगी।

हालांकि, जब तक कि आप लंबे समय तक रहा डुप्लिकेट वस्तुओं की बड़ी संख्या है, मुझे शक है कि होना शामिल है (या तो permGen में या अपने स्वयं के पूल के साथ) ज्यादा अंतर नहीं पड़ेगा। और यदि डुप्लिकेट ऑब्जेक्ट्स के अनूठे अनुपात का अनुपात बहुत कम है, तो इंटर्निंग केवल लाइव ऑब्जेक्ट्स की संख्या में वृद्धि करेगा (जीसी को अधिक समय तक ले जाएगा) और इंटर्निंग के ओवरहेड के कारण प्रदर्शन को कम करेगा, और इसी तरह। इसलिए मैं "इंटर्न" बनाम "कोई इंटर्न" दृष्टिकोण के बेंचमार्किंग का भी समर्थन नहीं करूंगा।

+0

एडमस्की में वास्तव में लंबी संख्या में, डुप्लिकेट ऑब्जेक्ट्स हैं :-) –

+0

@oxbow_lakes - बहुत चालाक। मुद्दा यह है कि आपको यह जानने के लिए इन चीजों को मापने की आवश्यकता है कि क्या इंटर्निंग (जो भी तंत्र द्वारा) प्रदर्शन में सुधार करता है ... या इससे भी बदतर हो जाता है। और परिणाम के प्रभाव के बहुत सारे कारक हैं। –

4

यदि आपके पास पहले से ही InternPool वर्ग है, तो ऐसा लगता है कि स्ट्रिंग्स के लिए एक अलग आंतरिक विधि चुनने के बजाय इसका उपयोग करना बेहतर है। विशेष रूप से String.intern() आपको वास्तव में आवश्यकतानुसार अधिक मजबूत गारंटी प्रदान करता है। आपका लक्ष्य स्मृति उपयोग को कम करना है, इसलिए जेवीएम के जीवनकाल के लिए सही इंटर्निंग वास्तव में आवश्यक नहीं है।

इसके अलावा, मैं Google CollectionsMapMaker का उपयोग करेंगे से बचने के लिए एक InternPool बनाने के लिए फिर से बनाने पहिया:

Map<BigDecimal,BigDecimal> bigDecimalPool = new MapMaker() 
    .weakKeys() 
    .weakValues() 
    .expiration(1, TimeUnits.MINUTES) 
    .makeComputingMap(
     new Function<BigDecimal, BigDecimal>() { 
     public BigDecimal apply(BigDecimal value) { 
      return value; 
     } 
     }); 

यह आपको (सही ढंग से लागू) कमजोर कुंजी और मूल्यों, धागा सुरक्षा देना होगा, स्वत: शुद्धिकरण पुरानी प्रविष्टियों और एक बहुत ही सरल इंटरफ़ेस (एक साधारण, जाने-माने Map)। यह सुनिश्चित करने के लिए कि आप खराब कोड मैसेजिंग से बचने के लिए Collections.immutableMap() का उपयोग करके इसे लपेट सकते हैं।

+0

ठीक है धन्यवाद। JVM के जीवनकाल के लिए String.intern() इंटर्न करता है? मुझे यकीन नहीं है कि यह सच है क्योंकि मैंने पर्मगेन से एकत्रित आधुनिक वीएम कचरा सोचा था। – Adamski

+0

@ जोचिम - आपको लगता है कि एक इंटर्न वाला स्ट्रिंग JVM के जीवन के लिए जी रहेगा। यह javadocs द्वारा गारंटी नहीं है, और वास्तव में मुझे नहीं लगता कि यह हालिया JVMs के लिए सच है। –

+0

@ स्टीफन: मैंने कोशिश नहीं की * नहीं *, क्योंकि जावाडॉक वास्तव में यह नहीं बताता है। –

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