2013-10-17 4 views
22

यह अभी तक एक और है "कृपया मुझे बताएं कि कैसे जावा कचरा कलेक्टर को चलाने के लिए मजबूर करना है" प्रश्न। हमारे आवेदन में, मेरा मानना ​​है कि हमारे पास ऐसा करने के अच्छे कारण हैं।काम करने के सेट के दौरान जावा कचरा कलेक्टर को चलाने के लिए कैसे मनाने के लिए छोटा है?

यह एक सर्वर अनुप्रयोग है, जो आमतौर पर लगभग 5 एम लाइव ऑब्जेक्ट्स होता है। प्रत्येक 5 मिनट में, हम एक विश्लेषण कार्य करते हैं जो ~ 60 सेकंड लेता है। यदि विश्लेषण चल रहा है, तो एक पूर्ण जीसी ट्रिगर किया गया है, तो लगभग 40 एम लाइव ऑब्जेक्ट्स होंगे। जब विश्लेषण पूरा हो जाता है तो अतिरिक्त 35 एम ऑब्जेक्ट कचरा बन जाते हैं। सर्वर हर समय अनुरोधों के लिए उत्तरदायी बने रहना चाहिए (भले ही विश्लेषण चल रहा हो)।

हमने पाया है कि विश्लेषण पूर्ण नहीं होने पर एक पूर्ण जीसी लगभग 1.5 सेकंड लेता है, लेकिन विश्लेषण चल रहा है, जबकि लगभग 15 सेकंड। दुर्भाग्यवश, हमारा आवंटन पैटर्न ऐसा है कि पूर्ण जीसी आमतौर पर विश्लेषण के दौरान ट्रिगर करते हैं, भले ही विश्लेषण केवल 20% समय चल रहा हो। (प्रत्येक तीसरा या चौथा विश्लेषण रन एक पूर्ण जीसी ट्रिगर करता है।)

मैंने विश्लेषण चलाने शुरू करने से पहले बहुत अधिक scorned System.gc() को कॉल करने के लिए कोड जोड़ा, यदि पुरानी पीढ़ी में खाली स्थान निश्चित सीमा से नीचे है (5GB)। लाभ बहुत महत्वपूर्ण था: हमें 15 सेकंड के विराम के समय 1.5 सेकंड पॉज़ टाइम्स मिल रहे हैं, और हम सौदा में अधिक कचरा मुक्त करते हैं। हालांकि, कभी-कभी System.gc() कॉल को अनदेखा कर दिया जाता है, और कुछ मिनट बाद जब हम स्वचालित रूप से जीसी ट्रिगर होता है तो हम 15-सेकंड रोकते हैं।

मेरा प्रश्न, तो: क्या कुछ ऐसा है जो हम कचरा कलेक्टर को चलाने के लिए दृढ़ता से मनाने के लिए कर सकते हैं? हम 1.7.0_0 9-आईसीएडीटीए चला रहे हैं और समांतर जीसी का उपयोग कर रहे हैं। मैं या तो (ए) कचरा संग्रह को मैन्युअल रूप से मजबूर करने के लिए एक विश्वसनीय तरीका चाहता हूं, या (बी) संग्राहक को ट्यून करने का कोई तरीका है ताकि यह एक अधिक बुद्धिमान स्वचालित निर्णय ले सके। (बी) मुश्किल लगता है, क्योंकि यह मुझे स्पष्ट नहीं है कि कलेक्टर कैसे पता लगा सकता है कि हमारा कामकाजी सेट इस नाटकीय फैशन में भिन्न होता है।

यदि आवश्यक हो तो मैं पर्याप्त हैकरी का सहारा लेना चाहता हूं; यह हमारे लिए एक गंभीर मुद्दा है। (हम सीएमएस या जी 1 कॉम्पैक्टरों को विकल्पों के रूप में देख सकते हैं, लेकिन मैं सीएमएस के थ्रूपुट प्रभाव को कम कर रहा हूं, और जी 1 बड़े बाइट एरे के चेहरे पर खराब व्यवहार करने के लिए प्रतिष्ठित है, जिसका हम उपयोग करते हैं।)

addendum: उत्पादन में, अब तक हमारा अनुभव रहा है कि System.gc() आमतौर पर एक पूर्ण कचरा संग्रह ट्रिगर करता है; कम से कम, उन परिस्थितियों में जहां हम इसे बुला रहे हैं। (हम केवल 10 से 30 मिनट में इसे एक बार कहते हैं, ढेर के साथ कुछ हद तक पूरी तरह से कचरे से भरा नहीं है।) कचरा संग्रह को अधिक विश्वसनीय रूप से ट्रिगर करने में सक्षम होना अच्छा होगा, लेकिन यह हमें ज्यादातर समय में मदद कर रहा है।

+0

आपने स्पष्ट रूप से अपना शोध किया है! मुझे आशा है कि आपको एक अच्छा जवाब मिलेगा; मैं इसके बारे में और जानने के लिए उत्सुक हूँ! – templatetypedef

+0

मैंने अक्सर इस बारे में सोचा है - वहां * कचरा संग्रह को मजबूर करने के वैध कारण हैं, हालांकि वे बहुत दुर्लभ प्रतीत होते हैं। शायद इसमें एक जीसी हुक के साथ एक विशेष जेवीएम की जरूरत है। – arcy

+0

क्या आपने केवल ढेर को छोटा करने की कोशिश की है? –

उत्तर

1

सीधे अपने प्रश्न का उत्तर देने के बजाय (मैं नहीं कर सकता), मैं एक संभावित विकल्प प्रदान करना चाहता हूं।

ऐसा लगता है कि आप अपने विश्लेषण चलाने के दौरान बड़ी संख्या में बड़े बाइट एरे आवंटित कर रहे हैं, और फिर दौड़ के अंत में उन्हें कचरा इकट्ठा करने की अनुमति दे रहे हैं (या अगली से पहले एकत्रित कचरा होने के लिए उन्हें मजबूर करने का प्रयास चलाने)।

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

यह विचार, निश्चित रूप से, अधिक जटिल डेटा संरचनाओं और ऑब्जेक्ट उदाहरणों तक बढ़ाया जा सकता है।

जब आपको इसकी आवश्यकता होती है तो स्मृति को आवंटित करने से यह थोड़ा अधिक काम होता है, और जब आप नहीं करते हैं तो इसे 'मुक्त' करते हैं, लेकिन कचरा कलेक्टर को जो काम करना है उस पर काफी कटौती करनी चाहिए।

5

आपकी समस्या यह है कि आप एक ही JVM में पूरी तरह से अलग-अलग आवश्यकताओं और मेमोरी प्रोफाइल के साथ दो अनुप्रयोग चला रहे हैं।

गैर-उपयोगकर्ता-सामना करने वाली प्रक्रिया में अलग-अलग डेटा विश्लेषण चलाएं, ताकि उपयोगकर्ता का सामना करने वाला सर्वर लगातार उत्तरदायी रहे। मुझे लगता है कि आवधिक विश्लेषण किसी प्रकार का सारांश या परिणाम डेटा उत्पन्न करता है; इसे उपयोगकर्ता के सामने वाले सर्वर पर भेजकर अंतिम उपयोगकर्ताओं को उपलब्ध कराएं ताकि इसे वहां से परोसा जा सके, या फिर आपका फ्रंट एंड विश्लेषण सर्वर से इसे अलग-अलग लाए।

+0

यह एक बुरा बिंदु नहीं है। दुर्भाग्य से, दो हिस्सों में गहराई से प्रवेश किया गया है, जो राज्य की एक महत्वपूर्ण राशि साझा कर रहा है। शायद उन्हें अलग करना संभव होगा लेकिन यह एक महत्वपूर्ण परियोजना होगी। हम इसे अंतिम उपाय के रूप में ले सकते हैं। (हमारे मामले में, सबसे बड़ी डेटा स्ट्रक्चर ऑफ-हेप को ले जाना, जैसा कि मार्टिनस सुझाव देता है, कुछ काम होगा लेकिन विश्लेषण को एक अलग प्रक्रिया में शिपिंग के रूप में मुश्किल नहीं है।) – Steve

2

बाइट एरे के स्थान पर गैर-प्रबंधित स्मृति, यानी ByteBuffer एस का उपयोग करने पर विचार करें।

मैं केवल एक हैक प्रदान कर सकता हूं जिसके लिए कुछ ट्यूनिंग की आवश्यकता होगी और फिर काम कर सकता है या नहीं। मैं पहले अधिक सौहार्द समाधान का प्रयास करता हूं। जब आप जीसी को मजबूर करना चाहते हैं, तो इसे बहुत सारी मेमोरी आवंटित करके करें। ऐसा करें ताकि स्मृति को तुरंत पुनः दावा किया जा सके, लेकिन पूरे आवंटन को अनुकूलित नहीं किया जा सकता है (sum += new byte[123456].hashCode() जैसे कुछ करना चाहिए)। कब रुकना है यह निर्धारित करने के लिए आपको एक विश्वसनीय विधि खोजनी होगी। फाइनलर वाला एक ऑब्जेक्ट आपको बता सकता है या शायद runtime.getFreeMemory देख सकता है।

+1

बहुत सारी मेमोरी आवंटित करके जीसी को मजबूर करना मुझे डराता है। मैं आसानी से इसे हल करने की तुलना में अधिक समस्याएं पैदा कर सकता था। हमें इसे ठीक से प्राप्त करना होगा, नियत पीढ़ी के जीसी को ट्रिगर करने के लिए पर्याप्त मेमोरी आवंटित करना होगा, लेकिन इतना नहीं कि आवंटन स्वयं सिस्टम को क्रश करता है (या सटीक समस्या का कारण बनने के लिए इतना लाइव डेटा बनाते हैं बचने के लिए)। गैर-प्रबंधित स्मृति एक समाधान हो सकता है; यह एक अनौपचारिक परियोजना होगी, लेकिन करने योग्य। हम पहले से ही हमारे सबसे बड़े डेटा संरचनाओं के लिए गैर-प्रबंधित स्मृति का उपयोग करते हैं, हमें कुछ विश्लेषण डेटा संरचनाओं को कवर करने के लिए इसे विस्तारित करना होगा। – Steve

-1

मैंने पाया कि जावा जीसी बड़ी संख्या में वस्तुओं (20-100 मीटर ऑब्जेक्ट्स) के साथ बहुत खराब तरीके से काम करता है। यदि आपकी वस्तु वास्तव में जीवित रहेगी, तो आपकी स्थिति और भी बदतर हो गई होगी, क्योंकि वास्तव में एकत्र करने के लिए कुछ भी नहीं होने पर भी जीसी भयानक होगा।

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

+0

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

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

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