2013-10-16 12 views
6

हम कुछ ओरेकल जेवीएम कचरा संग्रहण विकल्पों को ट्विक करने की कोशिश कर रहे हैं और एक डेवलपर ने यह सुनिश्चित करने के लिए -XX:PretenureSizeThreshold का उपयोग करने का प्रयास किया है ताकि तुरंत टेनेर में बड़ी मात्रा में ऑब्जेक्ट लगाए जा सकें। मुझे पूरा यकीन है कि धारणा यह थी कि सरणी का आकार सभी वस्तुओं के कुल आकार के बराबर या उससे अधिक है।जावा ऑब्जेक्ट्स के सरणी कैसे कार्यरत हैं?

लेकिन जावा में, ऑब्जेक्ट्स के सरणी नहीं हैं केवल संदर्भ के सरणी? अर्थात। सरणी में प्रत्येक ऑब्जेक्ट, साथ ही साथ सरणी ऑब्जेक्ट, स्मृति में अलग है और कचरा कलेक्टर द्वारा अलग के रूप में माना जाता है? मुझे लगता है कि यदि लाखों प्रविष्टियां हैं तो सरणी ऑब्जेक्ट अभी भी काफी बड़ा हो सकता है, लेकिन यह ऑब्जेक्ट के कुल आकार के पास कहीं भी नहीं होना चाहिए, यदि यह प्रत्येक संदर्भ किसी संदर्भ से बड़ा है।

मुझे लगता है कि क्योंकि AFAIK, सी में भ्रम की स्थिति नहीं है:

  1. यह struct कि वास्तव में struct रों की दुकान करता है की एक सरणी के लिए संभव है।
  2. पॉइंटर्स से struct एस की एक सरणी भी संभव है।

मुझे यकीन है कि जावा हमेशा प्राचीन प्रकार के सरणी के लिए उपयोग करता है और हमेशा 2 का उपयोग करता है। वस्तुओं के सरणी के लिए, जबकि सी किसी भी प्रकार के लिए उपयोग कर सकता है ...?

क्या होगा यदि मैं का उपयोग अक्सर append() एस (जैसा कि हम हाथ में हैं) के साथ करते हैं? केवल सरणी कॉपी की गई है, और सरणी में ऑब्जेक्ट्स नहीं है? साथ ही, जब सरणी की प्रतिलिपि बनाई जाती है, भले ही पुरानी सरणी टेनेर में थी, तब भी नया ईडन में शुरू होता है, है ना?

+0

आप मूल रूप से सही हैं। जावा में गैर-प्राइमेटिव्स की एक सरणी हमेशा संदर्भों की एक सरणी होती है।और यदि एक ऐरेलिस्ट को फिर से आवंटित किया जाता है तो नई सरणी "ताजा" शुरू होती है। (यह कहना नहीं है कि कुछ जेवीएम विशेष परिस्थितियों को विशेष परिस्थितियों में नहीं रखते हैं, लेकिन यह एक बहुत ही अलग होगा (यानी, बेंचमार्क महत्वपूर्ण) स्थिति पर लक्षित।) –

उत्तर

5

लेकिन जावा में, ऑब्जेक्ट्स के सरणी सिर्फ संदर्भों के सरणी नहीं हैं?

बस संदर्भ। सभी वस्तुओं को ढेर पर आवंटित किया जाता है, कभी भी सरणी या ढेर में नहीं (कम से कम आधिकारिक तौर पर, ऑप्टिमाइज़र यदि संभव हो तो स्टैक आवंटन का उपयोग कर सकता है, लेकिन यह पारदर्शी है)।

यह ऑब्जेक्ट्स के कुल आकार के पास कहीं भी नहीं होना चाहिए, यदि प्रत्येक ऑब्जेक्ट संदर्भ से बहुत बड़ा है।

हाँ, जब भी आप कहते हैं कि "ऑब्जेक्ट असाइन/स्टोर करें", तो आपका मतलब संदर्भ (सी टर्मिनोलॉजी में पॉइंटर) है।

क्या होगा यदि मैं लगातार ऐपेंड() के साथ एक ऐरेलिस्ट का उपयोग करता हूं (जैसा कि हम हाथ में हैं)? केवल सरणी कॉपी की गई है, और सरणी में ऑब्जेक्ट्स नहीं है?

सरणी केवल, की नकल की हो जाता है जब आकार बदलने की जरूरत है जैसे कि, बहुत मुश्किल से ही और परिशोधित लागत आवेषण की संख्या के लिए आनुपातिक है। संदर्भित वस्तुओं को कभी कॉपी नहीं किया जाता है।

इसके अलावा, जब सरणी की नकल की है, भले ही वर्ष सरणी पर्याप्त में था नया एक, सही ईडन में शुरू होता है?

हाँ!

+0

क्या आप एक ही चीज़ को उद्धृत करना चाहते थे दो बार? फिर भी, आपने सभी सवालों का जवाब दिया, इसलिए मैंने स्वीकार किया :) –

+0

वाह। यह भयानक लगता है, लेकिन शायद जावा का आवंटन डेटा आसन्नता को अधिकतम रखने के लिए पर्याप्त है। यदि नहीं .. अच्छा, यह खोए प्रदर्शन की त्रासदी है। – Thumbz

+0

@ थंबस: निश्चित रूप से, आवंटक स्थान एक दूसरे के बगल में पंक्ति में आवंटित ऑब्जेक्ट करता है (जब तक कि इसे स्वयं को एक नया मेमोरी हिस्सा न मिल जाए)। लेकिन फिर कॉम्पैक्टिंग जीसी आता है ... यह भी इलाके को संरक्षित करने की कोशिश करता है, लेकिन यह अधिक जटिल हो जाता है। कभी-कभी यह एक समस्या हो सकती है, लेकिन [सभी बुरी चीजों की जड़] को न भूलें (http://c2.com/cgi/wiki?PrematureOptimization)। – maaartinus

2

लेकिन जावा में, ऑब्जेक्ट्स के सरणी सिर्फ संदर्भों के सरणी नहीं हैं? अर्थात। सरणी में प्रत्येक ऑब्जेक्ट के साथ-साथ सरणी ऑब्जेक्ट, मेमोरी में अलग है और कचरा कलेक्टर द्वारा अलग के रूप में माना जाता है?

हां।

मुझे लगता है कि क्योंकि AFAIK, सी में भ्रम की स्थिति नहीं है:

  1. यह structs कि वास्तव में structs की दुकान करता है की एक सरणी के लिए संभव है।
  2. structs के लिए पॉइंटर्स की एक सरणी भी संभव है।

मैं यकीन है कि जावा हमेशा आदिम प्रकार की सरणियों के लिए 1. का उपयोग करता हूँ और हमेशा वस्तुओं की सरणियों के लिए 2. का उपयोग करता है, जबकि सी या तो किसी भी प्रकार के लिए उपयोग कर सकते हैं ...?

जावा, जैसे सी, आम तौर पर उन प्रकार के तत्वों के साथ वास्तविक सरणी के रूप में प्राचीन प्रकार के सरणी स्टोर करता है। इसलिए 0 तत्वों के साथ int[] सरणी आम तौर पर सरणी के लिए 10 × 4 बाइट आरक्षित करने जा रही है, साथ ही पूरे सरणी ऑब्जेक्ट के लिए ओवरहेड।

ऑब्जेक्ट्स की Arrays, जैसा कि आप कहते हैं, संदर्भ के सरणी हैं। इसलिए 10 तत्वों में से object[] आमतौर पर सरणी के लिए 10 × 4 बाइट्स (या शायद 64-बिट CPUs पर 10 × 8 बाइट्स) लेते हैं, प्रत्येक ऑब्जेक्ट के लिए प्रत्येक ऑब्जेक्ट के लिए प्लस ओवरहेड, प्लस स्पेस जो प्रत्येक गैर-शून्य तत्व संदर्भों के लिए होता है। यह सी में पॉइंटर्स की सरणी से मेल खाता है।

(मैं शब्द "आम तौर पर" का उपयोग करें, क्योंकि भले ही है कि कैसे सबसे JVMs यह करना है, वे नहीं आवश्यक किसी विशेष फैशन में स्मृति को आबंटित कर रहे हैं।)

भी अवगत जावा नहीं है कि हो सकता है सी (या सी #) जैसे वास्तविक बहु-आयामी सरणी। जावा में int[][] वास्तव में एक-आयामी सरणी है, जहां प्रत्येक तत्व अपने int[] उपराष्ट्रय का संदर्भ है। सी में, int[][] वास्तव में पूर्णांक की एक द्वि-आयामी सरणी है (जहां सभी आयामों की लंबाई संकलन समय पर ज्ञात होनी चाहिए)।

परिशिष्ट

भी ध्यान रखें कि, आप की तरह कहते हैं, सी structs का सच सरणियों, जो न तो आदिम प्रकार है और न ही संकेत दिए गए हैं हो सकता है। जावा में यह क्षमता नहीं है।

2

ट्यूनिंग के लिए -XX:PretenureSizeThreshold का उपयोग करने से आपकी मदद करने की संभावना नहीं है। यह पैरामीटर केवल ईडन आवंटन पर लागू होता है, जबकि अधिकांश आवंटन TLAB (थ्रेड लोकल आवंटन बफर) में हो रहा है और -XX:PretenureSizeThreshold को अनदेखा किया जाता है।

टीएलबी सक्रिय रूप से स्मृति आवंटित करने के लिए काफी बड़ा हो सकता है (कुछ मेगाबाइट्स)।

आप इस प्रभाव को कम करने के लिए टीएलबी आकार बदल सकते हैं, लेकिन यह संभवतः अच्छे से अधिक नुकसान करेगा।

+0

वाह। और मैंने सोचा कि मैं जीसी की जटिलता का एक अच्छा हिस्सा पहले से ही खोलांगा, केवल Google TLABs पर और [इस भयानक पोस्ट] में चलाएं (https://blogs.oracle.com/jonthecollector/entry/the_real_thing)। मैं पूरी तरह से सहमत हूं कि उस स्तर पर (और अधिकतर स्तरों पर) वीएम को अपने उपकरणों पर छोड़कर सबसे अच्छा शर्त है। पारितोषिक के लिए धन्यवाद! –

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