2015-01-21 3 views
6

मैं जावा में byte[] से String को deserialize करने के लिए एक रास्ता तलाश रहा हूं, जितना संभव हो उतना कचरा बनाया गया है। क्योंकि मैं अपना खुद का सीरिएलाइज़र और डी-सीरियलाइज़र बना रहा हूं, मेरे पास सर्वर-साइड (यानी डेटा को क्रमबद्ध करते समय) पर किसी भी समाधान को लागू करने की पूरी स्वतंत्रता है, और क्लाइंट-साइड पर (यानी जब डेटा को डी-सीरियलाइज किया जाता है)।जावा में ज़ीरो-कचरा बड़ा स्ट्रिंग deserialization, humongous ऑब्जेक्ट मुद्दा

मैं कुशलता से serialize एक StringString's वर्ण (String.charAt(i)) के माध्यम से पुनरावृत्ति और प्रत्येक char (16-बिट मूल्य) 8 बिट मूल्य 2 गुना तक परिवर्तित करके किसी भी कचरा भूमि के ऊपर किये बिना में कामयाब रहे। इस here के बारे में एक अच्छी बहस है। एक विकल्प String'sअंतर्निहित सीधे उपयोग करने के लिए प्रतिबिंब का उपयोग करना है, लेकिन यह समस्या के दायरे से बाहर है।

हालांकि, यह मुझे char[]दो बार, जो लगता है, ठीक है, अजीब बनाए बिना byte[] deserialize करने के लिए असंभव लगता है।

प्रक्रिया:

  1. byte[] के माध्यम से char[]
  2. दोहराएं बनाएँ और पूर्ति char[]
  3. बनाएं स्ट्रिंग String(char[]) निर्माता
क्योंकि जावा के String अचल स्थिति नियमों के

, निर्माता के साथ चार [x] प्रतिलिपि बनाते हैं, 2x जीसी ओवरहेड बनाते हैं। मैं हमेशाउदाहरण सेट करने के लिए इस असुरक्षित String आवंटन + प्रतिबिंब को रोकने के लिए तंत्र का उपयोग कर सकता हूं), लेकिन मैं सिर्फ यह पूछना चाहता था कि String's अपरिवर्तनीयता पर हर सम्मेलन को तोड़ने से मेरे पास कोई अन्य परिणाम है या नहीं।

बेशक, इसके लिए सबसे बुद्धिमान प्रतिक्रिया "आओ, इसे रोकें और जीसी में भरोसा रखें, मूलबेहद कम रहता है और जी 1 इसे क्षणिक रूप से छुटकारा पायेगा", जो वास्तव में समझ में आता है , यदि char[] जी 1 के क्षेत्र आकार के 1/2 से छोटा है। यदि यह बड़ा है, तो char [] को एक विशाल वस्तु के रूप में सीधे आवंटित किया जाएगा (यानी स्वचालित रूप से जी 1 के क्षेत्र के बाहर प्रचारित)। जी 1 में एकत्रित कुशलतापूर्वक कचरा होने के लिए ऐसी वस्तुएं बेहद मुश्किल हैं। यही कारण है कि प्रत्येक आवंटन मामलों।

इस मुद्दे से निपटने के तरीके पर कोई विचार?

बहुत धन्यवाद।

+0

क्या आपने स्ट्रिंग्स के साथ काम नहीं किया है और केवल कच्चे बाइट डेटा को क्रमबद्ध कर रहा है और जब यह बिल्कुल जरूरी है तो उपखंडों पर चरित्र सेट रूपांतरण कर रहा है? मेरे पास – the8472

+0

है। मेरा विचार था कि एक नया वर्ग 'म्यूटेबलस्ट्रिंग' बनाना है, और इस पर बहुत से परंपरागत रूप से कचरा-भारी संचालन लागू करना है (उदाहरण के लिए फास्टपाथ 'स्ट्रिंग' स्प्लिट), और फिर एक विधि 'toString (से, से)' बनाता है जो बनाता है एक "दृश्य" उदाहरण जो प्रकार 'स्ट्रिंग' प्रकार का है। मैं वह कर सकता था। लेकिन इसके लिए हमारे आवेदन को पूरी तरह से दोबारा करने और हर जगह संभवतः 'MutableString' का उपयोग करने की आवश्यकता होगी। यह एक अच्छा विचार है, लेकिन मैं पहले विकल्प तलाशना चाहता था। – SergioTCG

+1

क्या आप जानते हैं कि ये सभी चीजें पहले से मौजूद हैं? 'CharBuffer' और' StringBuilder' हैं, दोनों एक प्रकार का उत्परिवर्तनीय 'स्ट्रिंग' (जब तक कि आप एक अपरिवर्तनीय दृश्य नहीं बनाते), उनके हल्के वजन के निर्माण के तरीके हैं और वे सभी' CharSequence', 'इंटरफेस को लागू करते हैं 'जिस पर रेगेक्स पैकेज, जो वास्तव में' स्प्लिट 'ऑपरेशन लागू करता है, पर काम करता है। और जब यह * चरित्र सामग्री की तरह दिखता है, तो 'स्ट्रिंग', 'चारबफर' और 'स्ट्रिंगबिल्डर' के बीच कनवर्ट करते समय स्रोत कोड को देखते समय, हॉटस्पॉट के लिए विशेष अनुकूलन होता है ... – Holger

उत्तर

1

मुझे एक समाधान मिला है, जो बेकार है, अगर आपके पास एक अप्रबंधित वातावरण है।

java.lang.String कक्षा में पैकेज-निजी कन्स्ट्रक्टर String(char[] value, boolean share) है।

स्रोत:

/* 
* Package private constructor which shares value array for speed. 
* this constructor is always expected to be called with share==true. 
* a separate constructor is needed because we already have a public 
* String(char[]) constructor that makes a copy of the given char[]. 
*/ 
String(char[] value, boolean share) { 
    // assert share : "unshared not supported"; 
    this.value = value; 
} 

यह जावा के भीतर बड़े पैमाने पर इस्तेमाल किया जा रहा है, उदाहरण के लिए Integer.toString(), Long.toString(), String.concat(String), String.replace(char, char), String.valueOf(char) में।

समाधान (या हैक, जिसे आप इसे कॉल करना चाहते हैं) कक्षा को java.lang पैकेज पर ले जाने और पैकेज-निजी कन्स्ट्रक्टर तक पहुंचने के लिए है। यह सुरक्षा प्रबंधक के साथ अच्छी तरह से नहीं होगा, लेकिन इसे बाधित किया जा सकता है।

+5

आप शायद प्रतिबिंब के माध्यम से कन्स्ट्रक्टर तक पहुंच सकते हैं और फिर ऊपरी कॉलिंग से बचने के लिए कन्स्ट्रक्टर विधि के लिए एक विधि हैंडल/लैम्ब्डा बना सकते हैं – the8472

3

ऐसी वस्तुएं जी 1 में कुशलतापूर्वक कचरा एकत्र करने के लिए बहुत कठिन हैं।

यह अब सत्य नहीं हो सकता है, लेकिन आपको इसे अपने आवेदन के लिए मूल्यांकन करना होगा। जेडीके बग 8027959 और 8048179 भारी, अल्पकालिक वस्तुओं को इकट्ठा करने के लिए नए तंत्र पेश करते हैं। बग झंडे के मुताबिक आपको अपने संबंधित लाभों काटने के लिए jdk संस्करण ≥8u40 और ≥8u60 के साथ चलना पड़ सकता है।ब्याज की

प्रायोगिक विकल्प:

-XX:+G1ReclaimDeadHumongousObjectsAtYoungGC 

ट्रेसिंग:

-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC 

आगे की सलाह और उन सुविधाओं मैं hotspot-gc-use मेलिंग सूची से टकराने की सिफारिश करेंगे संबंधित प्रश्नों के लिए।

+0

धन्यवाद, मैं जरा देखो तो। पैकेज में कक्षा को स्थानांतरित करने के बजाय – SergioTCG

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