को कम करना JVM विराम समय> 1 UseConcMarkSweepGC


10

का उपयोग कर दूसरी मैं रैम 16GB, और एक 8-कोर प्रोसेसर, और जावा 1.6 के साथ एक मशीन पर एक स्मृति गहन एप्लिकेशन चल रहा हूँ रिहाई 5.2 (अंतिम) CentOS पर चल रहा है। सटीक JVM विवरण हैं:

java version "1.6.0_10" 
Java(TM) SE Runtime Environment (build 1.6.0_10-b33) 
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode) 

मैं निम्नलिखित कमांड लाइन विकल्पों के साथ एप्लिकेशन को लॉन्च कर रहा हूँ:

java -XX:+UseConcMarkSweepGC -verbose:gc -server -Xmx10g -Xms10g ... 

मेरा आवेदन एक JSON-RPC एपीआई को उजागर करता है, और मेरा लक्ष्य के भीतर अनुरोध का जवाब देना है 25ms। दुर्भाग्यवश, मुझे 1 सेकंड तक की देरी हो रही है और यह कचरा संग्रह के कारण होता है।

[GC 4592788K->4462162K(10468736K), 1.3606660 secs] 
[GC 5881547K->5768559K(10468736K), 1.2559860 secs] 
[GC 6045823K->5914115K(10468736K), 1.3250050 secs] 

इन कचरा संग्रहण की घटनाओं में से प्रत्येक कचरा संग्रहण से पता चला की लंबाई के बहुत समान अवधि का एक देरी एपीआई प्रतिक्रिया से (कुछ एमएस के भीतर करने के लिए) भी थे: यहाँ अब कुछ उदाहरण हैं।

यहां कुछ सामान्य उदाहरण (इन सभी कुछ सेकंड के भीतर उत्पादन किया गया था) कर रहे हैं:

[GC 3373764K->3336654K(10468736K), 0.6677560 secs] 
[GC 3472974K->3427592K(10468736K), 0.5059650 secs] 
[GC 3563912K->3517273K(10468736K), 0.6844440 secs] 
[GC 3622292K->3589011K(10468736K), 0.4528480 secs] 

बात मैंने सोचा था कि UseConcMarkSweepGC या इससे बचने के हैं, कम से कम यह अत्यंत दुर्लभ बनाते हैं। इसके विपरीत, 100 मिमी से अधिक की देरी लगभग एक मिनट या उससे अधिक बार होती है (हालांकि 1 सेकंड से अधिक की देरी काफी दुर्लभ होती है, शायद हर 10 या 15 मिनट में)।

दूसरी बात मैंने सोचा था कि केवल एक पूर्ण जीसी कारण होगा धागे रोका जाना था, अभी तक इन पूर्ण होने के लिए जेंटलमैन कैडेट दिखाई नहीं देते है।

यह ध्यान रखें कि स्मृति के सबसे एक LRU मेमोरी कैश कि मुलायम संदर्भ का उपयोग करता है के कब्जे में है प्रासंगिक हो सकता है।

किसी भी सहायता या सलाह बहुत सराहना की जाएगी।

+1

क्या जेडीके/जेआरई और क्या ओएस? 22 feb. 092009-02-22 00:40:22

+1

क्षमा करें, बस उस जानकारी को 22 feb. 092009-02-22 00:43:58

6

यह साबित करता है कि ढेर के उस भाग को डिस्क पर बदल दिया गया था, ताकि कचरा संग्रह को डिस्क से डेटा को वापस मेमोरी में खींच लिया जाए।

मैंने लिनक्स के "swappiness" पैरामीटर को 0 पर सेट करके हल किया (ताकि यह डिस्क पर डेटा को स्वैप नहीं करेगा)।

+3

मुझे एहसास है कि यह बहुत समय पहले से है, लेकिन भविष्य के आगंतुकों के लिए: इस आकार के ढेर पर, जावा के लिए ह्यूजेपेज सक्षम करने पर विचार करें। ह्यूजेपेज भी गैर-स्वीकार्य हैं, इसलिए वे स्वैपिंग समस्या को हल करेंगे। 04 oct. 112011-10-04 14:43:08


0

कुछ स्थानों की तलाश शुरू करने के लिए:

इसके अलावा, मैं एक प्रोफाइलर के माध्यम से कोड को चलाने चाहते हैं .. मैं NetBeans में एक पसंद है, लेकिन अन्य भी हैं। आप वास्तविक समय में जीसी व्यवहार देख सकते हैं। विजुअल वीएम भी ऐसा करता है ... लेकिन मैंने इसे अभी तक नहीं चलाया है (किसी कारण की तलाश में है ... लेकिन अभी तक समय या आवश्यकता नहीं है)।


0

मैं भी GCViewer और एक प्रोफाइलर सुझाव देना चाहेंगे।


11

सबसे पहले, Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning दस्तावेज़ीकरण देखें अगर आप पहले से ही ऐसा नहीं किया है। यह प्रलेखन कहते हैं:

समवर्ती कलेक्टर अपनी ट्रेसिंग और आवेदन धागे अभी भी चल रहा साथ व्यापक काम के सबसे करता है, इसलिए केवल संक्षिप्त विराम आवेदन धागे से देखा जाता है।हालांकि, यदि समवर्ती संग्राहक समाप्त करने में असमर्थ है, तो बीमित पीढ़ी भरने से पहले पहुंचने योग्य वस्तुओं को पुनः प्राप्त करने के लिए, या एक आवंटन कार्यरत पीढ़ी में उपलब्ध खाली स्थान ब्लॉक से संतुष्ट नहीं हो सकता है, तो आवेदन रोक दिया गया है और संग्रह सभी आवेदन धागे बंद होने के साथ पूरा हो गया है। संग्रह को पूरा करने में असमर्थता समवर्ती रूप से समवर्ती मोड विफलता के रूप में जाना जाता है और समवर्ती संग्राहक पैरामीटर समायोजित करने के लिए की आवश्यकता को इंगित करता है।

और बाद में एक छोटा सा ...

समवर्ती कलेक्टर एक समवर्ती संग्रह चक्र के दौरान दो बार एक आवेदन रुक जाता है।

मुझे पता है कि उन जीसी बहुत मेमोरी को मुक्त नहीं कर रहे हैं। शायद आपकी कई वस्तुएं लंबे समय तक रहती हैं? आप पीढ़ी के आकार और अन्य जीसी पैरामीटर को ट्यून करना चाहते हैं। 10 गीग विशाल कई मानकों से ढेर है, और मैं उम्मीद करता हूं कि जीसी इतनी बड़ी ढेर के साथ अधिक समय लेगा। फिर भी, 1 सेकंड एक बहुत लंबा विराम समय है और यह इंगित करता है कि कुछ गलत है (आपका प्रोग्राम अनियंत्रित वस्तुओं की एक बड़ी संख्या उत्पन्न कर रहा है या वस्तुओं को मुश्किल से पुनः प्राप्त कर रहा है, या कुछ और) या आपको बस जीसी को ट्यून करने की आवश्यकता है।

आमतौर पर, मैं किसी को बता दूंगा कि अगर उन्हें जीसी ट्यून करना है तो उन्हें अन्य समस्याओं को पहले ठीक करने की आवश्यकता है। लेकिन इस आकार के आवेदन के साथ, मुझे लगता है कि आप "औसत प्रोग्रामर से अधिक जीसी को समझने की आवश्यकता" के क्षेत्र में आते हैं।

जैसा कि अन्य ने कहा है, आपको यह देखने के लिए अपने आवेदन को प्रोफ़ाइल करने की आवश्यकता है कि बाधा कहां है। क्या आपके परमसेन आवंटित स्थान के लिए बहुत बड़ा है? क्या आप अनावश्यक वस्तुएं बना रहे हैं? jconsole कम से कम वीएम के बारे में कम से कम जानकारी दिखाने के लिए काम करता है। यह एक शुरुआती बिंदु है। जैसा कि अन्य ने संकेत दिया है, आपको इसकी तुलना में अधिक उन्नत टूल की आवश्यकता है।

शुभकामनाएं।


1

यहां कुछ चीजें हैं जो मुझे मिली हैं जो महत्वपूर्ण हो सकती हैं।

  • JSON-RPC कई ऑब्जेक्ट उत्पन्न कर सकता है। एक्सएमएल-आरपीसी जितना ज्यादा नहीं, लेकिन अभी भी कुछ देखने के लिए। किसी भी मामले में आप प्रति सेकेंड 100 एमबी ऑब्जेक्ट्स पर उतना ही उत्पन्न कर रहे हैं जिसका अर्थ है कि आपका जीसी उस समय का उच्च प्रतिशत चल रहा है और आपकी यादृच्छिक विलंबता में जोड़ने की संभावना है। भले ही जीसी समवर्ती है, फिर भी आपके हार्डवेयर/ओएस लोड के तहत गैर आदर्श यादृच्छिक विलंबता प्रदर्शित करने की संभावना है।
  • अपनी मेमोरी बैंक आर्किटेक्चर पर नज़र डालें। लिनक्स पर कमांड numactl - hardware है। यदि आपका वीएम एक से अधिक मेमोरी बैंक में विभाजित किया जा रहा है तो इससे आपके जीसी टाइम्स में काफी वृद्धि होगी। (यह आपके एप्लिकेशन को भी धीमा कर देगा क्योंकि ये एक्सेस काफी कम कुशल हो सकती हैं) जितना कठिन आप स्मृति उपप्रणाली को काम करते हैं, उतना अधिक संभावना है कि ओएस को स्मृति को चारों ओर स्थानांतरित करना होगा (अक्सर बड़ी मात्रा में) और आपको परिणामस्वरूप नाटकीय विराम मिलते हैं (100 एमएस आश्चर्यजनक नहीं है)। भूलें कि आपका ओएस सिर्फ आपके ऐप को चलाने से ज्यादा नहीं करता है।
  • अपने कैश की स्मृति खपत को कम करने/घटाने पर विचार करें। यदि आप एकाधिक जीबी कैश का उपयोग कर रहे हैं तो यह आपके पास पहले से ही स्मृति खपत को कम करने के तरीकों को देखने लायक है।
  • मेरा सुझाव है कि आप एक ही समय में मेमोरी आवंटन ट्रेसिंग और सीपीयू नमूनाकरण के साथ अपने ऐप को प्रोफाइल करें। यह बहुत अलग परिणाम पैदा कर सकता है और अक्सर इस तरह की समस्याओं के कारण को इंगित करता है।

इन तरीकों का उपयोग करना, एक RPC कॉल की विलंबता नीचे 200 माइक्रो-दूसरे और जीसी बार 1-3 कॉल की कम से कम 1/300 प्रभावशाली एमएस करने के लिए कम को कम किया जा सकता है।


11

चूंकि आप कैश की अपनी इच्छा का जिक्र करते हैं, तो मुझे लगता है कि आपके अधिकांश विशाल ढेर उस कैश पर कब्जा कर लिया गया है। आप कैश के आकार को सीमित करना चाहते हैं ताकि आप सुनिश्चित हों कि यह कभी भी कार्यरत पीढ़ी को भरने के लिए पर्याप्त रूप से बड़ा होने का प्रयास नहीं करता है। आकार को सीमित करने के लिए अकेले SoftReference पर भरोसा न करें। चूंकि पुरानी पीढ़ी नरम संदर्भों से भरती है, पुराने संदर्भों को मंजूरी दे दी जाएगी और कचरा बन जाएगा। नए संदर्भ (शायद एक ही जानकारी के लिए) बनाए जाएंगे, लेकिन जल्दी से मंजूरी दे दी जाएगी क्योंकि मुफ्त स्थान कम आपूर्ति में है। आखिरकार, कार्यरत जगह कचरे से भरी हुई है और इसे साफ करने की जरूरत है।

-XX:NewRatio सेटिंग को समायोजित करने पर विचार करें। डिफ़ॉल्ट 1: 2 है, जिसका अर्थ है कि एक तिहाई ढेर नई पीढ़ी को आवंटित किया जाता है। एक बड़े ढेर के लिए, यह लगभग हमेशा बहुत अधिक है। आप 9 की तरह कुछ कोशिश करना चाहेंगे, जो आपकी पीढ़ी के लिए 10   जीबी ढेर के 9   जीबी रखेगा।

+1

+1 जोड़ा गया। यह -XX: न्यूराटियो के बारे में एक बहुत अच्छा मुद्दा है। 22 feb. 092009-02-22 03:25:04

  0

हाँ, मुझे लगता है कि यह एक ऐसा चीज है जिसे हम सभी ट्यून करते समय याद करते हैं। 21 oct. 102010-10-21 08:37:21


0

कुछ चीजें हैं जो मुझे आशा है कि मदद कर सकते हैं:

मैं ConcurrentCollector साथ अच्छे भाग्य की भी था कभी नहीं किया है, सिद्धांत रूप में यह कम विलंबता के लाभ के लिए प्रवाह क्षमता बलिदान, लेकिन मैं के साथ बेहतर किस्मत मिल गया है थ्रूपुट कलेक्टर दोनों थ्रूपुट और विलंबता (ट्यूनिंग के साथ, और मेरे ऐप्स के लिए)।

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

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

इसका मतलब क्या है आपकी वस्तुओं है कि युवा पीढ़ी में रहते हैं कि कैश में डाल रहे हैं अब कई बार कॉपी कर रहे हैं है, जिंदा रखा, उनके संदर्भ जीवित रखने, और आम तौर youngGen जीसी धीमा।

इसकी तरह का विरोधाभासी कैशिंग कैबिंग ऑब्जेक्ट आवंटन को कम कर सकती है लेकिन जीसी समय बढ़ाती है।

आप अपने उत्तरजीवी अनुपात को समायोजित करने का प्रयास भी कर सकते हैं, यह नियत पीढ़ी में और भी अधिक 'युवा' वस्तुओं को बहाना बहुत छोटा हो सकता है।


0

मैं व्यक्तिगत रूप से इतना बड़ा ढेर नहीं इस्तेमाल किया है, लेकिन मैं Oracle/सन जावा 1.6.x के लिए सामान्य निम्नलिखित स्विच का उपयोग करने में बहुत कम विलंबता अनुभव किया है:

-Xincgc -XX:+UseConcMarkSweepGC -XX:CMSIncrementalSafetyFactor=50 
-XX:+UseParNewGC 
-XX:+CMSConcurrentMTEnabled -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 
-XX:CMSIncrementalDutyCycleMin=0 -XX:CMSIncrementalDutyCycle=5 
-XX:GCTimeRatio=90 -XX:MaxGCPauseMillis=20 -XX:GCPauseIntervalMillis=1000 

महत्वपूर्ण भागों में हैं, मेरे राय, युवा पीढ़ी के लिए कार्यकाल पीढ़ी और ParNewGC के लिए सीएमएस का उपयोग। इसके अलावा, यह सीएमएस के लिए एक बहुत बड़ा सुरक्षा कारक जोड़ता है (डिफ़ॉल्ट 50% के बजाय 10% है) और छोटे विराम के समय का अनुरोध करें। चूंकि आप 25 एमएस प्रतिक्रिया समय के लिए लक्ष्यीकरण कर रहे हैं, तो मैं -XX:MaxGCPauseMillis को छोटे मान तक सेट करने का प्रयास करूंगा।आप समवर्ती जीसी के लिए दो से अधिक कोर का उपयोग करने का भी प्रयास कर सकते हैं लेकिन मैं अनुमान जो CPU उपयोग के लायक नहीं है।

आपको शायद HotSpot JVM GC cheat sheet भी देखना चाहिए।