2012-03-16 11 views
11

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

1) सीरियल: -XX: + UseSerialGC

2) समानांतर: -XX: + UseParallelOldGC

मैं चार विभिन्न तकनीकों, जो कचरा संग्रहण नियंत्रित करने के लिए निम्नलिखित झंडे का उपयोग कोशिश कर रहा हूँ

3) समवर्ती: -XX: + UseConcMarkSweepGC

4) समवर्ती/वृद्धिशील: -XX: + UseConcMarkSweepGC -XX: + CMSIncrementalMode -XX: + CMSIncrementalPacing

मैंने पांच घंटे के दौरान प्रत्येक तकनीक को चलाया। मैंने समय-समय पर कचरा इकट्ठा करने में व्यतीत कुल समय को पुनः प्राप्त करने के लिए प्रबंधन Factory.getGarbageCollectorMXBeans() द्वारा प्रदान किए गए GarbageCollectorMXBean की सूची का उपयोग किया।

मेरे परिणाम? ध्यान दें कि "विलंबता" यहां "समय की राशि है कि मेरा आवेदन + एपीआई नेटवर्क से हटाए गए प्रत्येक संदेश को संसाधित करने में व्यतीत करता है।"

सीरियल: 78 9 जीसी कुल 130 9 एमएस की घटनाएं; औसत विलंबता 47.45 हमें, औसत विलंबता 8.704 हमें, अधिकतम विलंबता 1197 हमें

समांतर: 1715 जीसी कार्यक्रम कुल 122518 एमएस; औसत विलंबता 450.8 हमें, औसत विलंबता 8.448 हमें, अधिकतम विलंबता 8292 हमें

समवर्ती: 4629 जीसी घटनाएं कुल 11622 9 एमएस; औसत विलंबता 707.2 हमें, औसत विलंबता 9.216 हमें, अधिकतम विलंबता 9151 हमें

वृद्धिशील: 200663 एमएस की कुल 5066 जीसी घटनाएं; औसत विलंबता 515.9 हमें, औसत विलंबता 9.472 हमें, अधिकतम विलंबता 1420 9 हमें

मुझे ये परिणाम इतने असंभव होने के लिए मिलते हैं कि वे बेतुका पर सीमा बनाते हैं। क्या किसी को पता है कि मुझे इस तरह के नतीजे क्यों हो सकते हैं?

ओह, और रिकॉर्ड के लिए, मैं जावा हॉटस्पॉट (टीएम) 64-बिट सर्वर वीएम का उपयोग कर रहा हूं।

+0

क्या आप मानते हैं कि समानांतर में दो चीजों को निष्पादित करना एक चीज़ के बाद एक चीज़ को निष्पादित करने से तेज़ है? – aioobe

+0

मुझे उम्मीद है कि अधिकतम विलंबता – jcoder

+0

हालांकि बढ़ जाएगी, तो, आपके अलग-अलग परिदृश्यों में उन 5 घंटों में वास्तव में कितने संदेश संसाधित किए गए थे? क्या आप एक धागा चला रहे हैं, या बहुप्रचारित? – pap

उत्तर

18

मैं एक जावा अनुप्रयोग है कि उस के साथ प्रवाह क्षमता को अधिकतम करने और विलंबता

दो समस्याओं को कम करने की उम्मीद है पर काम कर रहा हूँ:

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

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

// Avoid generating any garbage 
Thread.sleep(10000000); 

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

+1

+1 ग्रेट उत्तर। काश मैं कचरा उत्पन्न करने से बचने के लिए अपने समाधान के लिए एक अतिरिक्त +1 दे सकता हूं :-) – aioobe

+0

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

+0

हाहा। _ कोई भी garbage_ उत्पन्न करने के लिए .. बस महान! +1 – kromit

0

आप यह नहीं कह सकते कि एक जीसी दूसरे की तुलना में बेहतर है। यह आपकी आवश्यकताओं और आपके आवेदन पर निर्भर करता है।

लेकिन यदि आप थ्रूपुट को अधिकतम करना चाहते हैं और विलंबता को कम करना चाहते हैं: जीसी आपका दुश्मन है! आपको जीसी को बिल्कुल कॉल नहीं करना चाहिए और जीवी को जीसी से कॉल करने से रोकने की भी कोशिश करनी चाहिए।

धारावाहिक के साथ जाएं और ऑब्जेक्ट पूल का उपयोग करें।

4

मुझे यह आश्चर्यजनक नहीं लगता है।

सीरियल कचरा संग्रह के साथ समस्या यह है कि यह चल रहा है, और कुछ भी नहीं चल सकता है (उर्फ "दुनिया को रोकता है")। हालांकि यह एक अच्छा मुद्दा है: यह कचरा संग्रह पर खर्च किए गए काम की मात्रा को केवल न्यूनतम के बारे में बताता है।

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

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

अब, मैं क्यों कहूं कि शायद इस मामले में मामूली योगदानकर्ता है? यह बहुत आसान है: सीरियल कलेक्टर केवल पांच घंटों में से एक सेकंड में थोड़ा सा उपयोग करता था। हालांकि ~ 1.3 सेकंड के दौरान कुछ भी नहीं किया गया है, यह पांच घंटे का इतना छोटा प्रतिशत है कि संभवतः यह आपके समग्र थ्रूपुट में कोई वास्तविक (यदि कोई हो) वास्तविक अंतर नहीं बना।

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

2

इस विषय पर 2012 QCon Conference पर ट्विटर इंजीनियर द्वारा एक उत्कृष्ट बात की गई - आप इसे here देख सकते हैं।

इसने हॉटस्पॉट जेवीएम मेमोरी और कचरा संग्रह (ईडन, उत्तरजीवी, पुरानी) में विभिन्न "पीढ़ियों" पर चर्चा की। विशेष रूप से ध्यान दें कि ConcurrentMarkAndSweep में "समवर्ती" केवल पुरानी पीढ़ी पर लागू होता है, यानी ऑब्जेक्ट्स जो थोड़ी देर के लिए घूमते हैं।

अल्पकालिक वस्तुओं "ईडन" पीढ़ी से जीसीडी हैं - यह सस्ता है, लेकिन एक "स्टॉप-द-वर्ल्ड" जीसी घटना है चाहे आप किस जीसी एल्गोरिदम को चुना है!

सलाह युवा पीढ़ी को पहले ट्यून करना था। बहुत से नए ईडन आवंटित करें ताकि ऑब्जेक्ट्स युवाओं को मरने के लिए और मौके पर पुनः दावा किया जा सके। + प्रिंट GCDetails का उपयोग करें, + PrintHeapAtGC, + PrintTenuringDistribution ... यदि आपको 100% से अधिक जीवित व्यक्ति मिलते हैं तो कमरा नहीं था, इसलिए ऑब्जेक्ट्स को जल्दी से पुराने में प्रचारित किया जाता है - यह खराब है।

पुराने जेनरेटियोन के लिए ट्यूनिंग करते समय, यदि विलंबता शीर्ष प्राथमिकता है, तो पहले से ही ऑटो-ट्यून (+ एडैप्टिव साइज पॉलिसी आदि) के साथ समानांतर को आजमाने की अनुशंसा की जाती है, फिर सीएमएस की कोशिश करें, फिर शायद नया जी 1 जीसी।

+0

स्लाइड्स http://www.slideshare.net/aszegedi/everything-i-ever-learned-about-jvm-performance-tuning-twitter पर भी उपलब्ध हैं, यदि ऊपर दिया गया लिंक आपके लिए काम नहीं कर रहा है। – ryenus

+0

धन्यवाद - मैंने वीडियो के नए स्थान को इंगित करने के लिए मेरे उत्तर में लिंक भी अपडेट किया है। – DNA

0

सीरियल संग्रह के साथ, एक समय में केवल एक चीज होती है। उदाहरण के लिए, यहां तक ​​कि जब कई CPUs उपलब्ध हैं, तब भी संग्रह का प्रदर्शन करने के लिए केवल एक का उपयोग किया जाता है। जब समानांतर संग्रह का उपयोग किया जाता है, कचरा संग्रह का कार्य भागों में विभाजित होता है और उन उप-वर्गों को अलग-अलग CPU पर निष्पादित किया जाता है। एक साथ ऑपरेशन संग्रह को की कुछ अतिरिक्त जटिलता और संभावित विखंडन के खर्च पर अधिक तेज़ी से करने में सक्षम बनाता है।

जबकि सीरियल जीसी जीसी को संसाधित करने के लिए केवल एक धागा का उपयोग करता है, समानांतर जीसी जीसी को संसाधित करने के लिए कई धागे का उपयोग करता है, और इसलिए तेज़ी से। यह जीसी उपयोगी है जब पर्याप्त स्मृति और बड़ी संख्या में कोर हैं। इसे "थ्रुपुट जीसी" भी कहा जाता है।

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