जावा प्रक्रिया में मेमोरी की क्या खपत होती है?


20

हम मध्यम भार के तहत जावा प्रक्रिया के मेमोरी उपयोग की जांच करने की कोशिश कर रहे हैं।

  PID   USER    PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
  12663 test    20   0 8378m 6.0g 4492 S   43  8.4 162:29.95 java

जैसा कि आप देख सकते हैं कि हमारे पास 6 जीबी पर निवासी मेमोरी है। अब दिलचस्प हिस्सा यह है: इस प्रक्रिया को इन पारमों के साथ निष्पादित किया जाता है:

  • -Xmx2048m
  • -Xms2048m
  • -XX: NewSize = 512 एम
  • -XX: MaxDirectMemorySize = 256M
  • ... जीसी और सामान के लिए कुछ अन्य

इन सेटिंग्स को देखते हुए और वास्तविक स्मृति उपयोग पर हम इस प्रक्रिया का उपयोग करने के लिए क्या उम्मीद करते हैं और वास्तव में इसका उपयोग करते हैं, इसका अंतर देखने के लिए हम लड़खड़ा गए हैं।

आमतौर पर हमारी मेमोरी प्रॉब्लम हीप डंप का विश्लेषण करके हल की जाती है लेकिन इस मामले में हमारी मेमोरी का इस्तेमाल कहीं न कहीं बाहर ही किया जाता है।

प्रश्न: ऐसे उच्च मेमोरी उपयोग के कारण को खोजने और जानने के लिए क्या कदम होंगे? उस प्रक्रिया में मेमोरी का उपयोग करने वाले उपकरणों को पहचानने में हमारी क्या मदद कर सकती है?

EDIT 0

ऐसा नहीं लगता है कि यह एक ढेर से संबंधित समस्या है क्योंकि हमारे पास अभी भी काफी कुछ जगह है:

jmap -heap 12663

परिणाम (अंतरिक्ष को बचाने के लिए संपादित)

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize      = 2147483648 (2048.0MB)
NewSize          = 536870912 (512.0MB)
MaxNewSize       = 536870912 (512.0MB)
OldSize          = 1610612736 (1536.0MB)
NewRatio         = 7
SurvivorRatio    = 8
PermSize         = 21757952 (20.75MB)
MaxPermSize      = 85983232 (82.0MB)

New Generation: 45.7% used
Eden Space: 46.3% used
From Space: 41.4% used
To Space: 0.0% used
concurrent mark-sweep generation: 63.7% used
Perm Generation: 82.5% used

EDIT 1

pmap का उपयोग करके हम देख सकते हैं कि 64Mb के आवंटन की काफी राशि है:

pmap -x 12663 | grep rwx | sort -n -k3 | less

का परिणाम:

... a lot more of these 64Mb chunks
00007f32b8000000       0   65508   65508 rwx--    [ anon ] <- what are these?
00007f32ac000000       0   65512   65512 rwx--    [ anon ]
00007f3268000000       0   65516   65516 rwx--    [ anon ]
00007f3324000000       0   65516   65516 rwx--    [ anon ]
00007f32c0000000       0   65520   65520 rwx--    [ anon ]
00007f3314000000       0   65528   65528 rwx--    [ anon ] 
00000000401cf000       0  241904  240980 rwx--    [ anon ] <- Direct memory ?
000000077ae00000       0 2139688 2139048 rwx--    [ anon ] <- Heap ?

तो कैसे पता करें कि वो 64Mb चंक कौन से हैं? उनका क्या उपयोग है? उनमें किस तरह का डेटा है?

धन्यवाद


2
मुझे ठीक वैसी ही समस्या हुई ... यहाँ मेरा सवाल है। stackoverflow.com/questions/18734389/… क्या आपके पास इस बारे में कोई हल है?
DeepNightTwo

जवाबों:


21

यह समस्या इस glibc समस्या से संबंधित हो सकती है ।

मूल रूप से, जब आपके पास मेमोरी आवंटित करने वाले कई थ्रेड होते हैं, तो ग्लिबेक लॉक विवाद से बचने के लिए आवंटन करने के लिए उपलब्ध एरेनास की संख्या को बढ़ा देगा। एक अखाड़ा 64Mb बड़ा है। ऊपरी सीमा कोरस एरेनास के 8 गुना सुन्न बनाने के लिए है। Arenas की मांग पर बनाया जाएगा जब एक थ्रेड पहुंचता है जो पहले से ही बंद है इसलिए यह समय के साथ बढ़ता है।

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

आपके pmap की संभावना नीचे इस तरह की लिस्टिंग है। ध्यान दें कि 324K + 65212K = 65536K, 560K + 64976K == 65536K, 620K + 64916K == 65536K। यही है, वे 64Mb तक का योग करते हैं।

00007f4394000000 324K आरडब्ल्यू --- [एनोन]
00007f4394051000 65212K ----- [एनोन]
00007f4398000000 560K rw --- [एनोन]
00007f439808c000 64976K ----- [आन]
00007f439c000000 620K rw --- [एनोन]
00007f439c09b000 64916K ----- [एनोन]

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


5
Xmx और Xms को एक ही मान पर सेट करने के साथ-साथ पर्यावरण वैरिएबल "निर्यात MALLOC_ARENA_MAX = 4" को sh स्क्रिप्ट में सेट करना जो हमारी वेब सेवा को शुरू करने में मदद करता है। इससे पहले हम हर 2 से 8 घंटे में OOM Killer के कारण वेब सेवा पुनरारंभ का अनुभव कर रहे थे। Ubuntu 14.04 में GLIBC संस्करण 2.19 है, जो अच्छा है, क्योंकि इसे होने की आवश्यकता है> = 2.16 MALLOC_ARENA_MAX के लिए काम करने की सेटिंग
Kluyg

यह जवाब और उपरोक्त टिप्पणी मेरे लिए एक जीवनसाथी थी। मेरे मामले में MALLOC_ARENA_MAX = 1 आवश्यक और प्रभावी था।
जॉन बाकिर

3

कैसे लाम्डा जांच के बारे में ? अन्य बातों के अलावा, यह आपको नीचे दिए गए स्क्रीनशॉट के समान मेमोरी उपयोग ब्रेकडाउन दिखा सकता है:

लैंबडा जांच मेमोरी उपयोग दृश्य

कभी-कभी pmap -x your_java_pidमददगार भी हो सकते हैं।


आपके उत्तर के लिए धन्यवाद। अगर मैं सही तरीके से समझूं तो लैम्ब्डा प्रोब अपाचे टोमैट के लिए है? जिसका हम उपयोग नहीं करते हैं ... शाम के बारे में मैं शीर्ष पद पर जानकारी जोड़ूंगा
कॉन्स्टेंटिन एस।

2

JProfiler कुछ तुम चाहते हो सकता है, लेकिन यह मुफ़्त नहीं है। जावा प्रक्रिया की मेमोरी उपयोग की जांच करने के लिए एक और अच्छा और मुफ्त टूल जावा विजुअलवीएम ओरेकल / सन जेडडीके वितरण में जेडीके उपकरण के रूप में उपलब्ध है। मैं व्यक्तिगत रूप से समस्या के लिए अधिक समग्र दृष्टिकोण की सिफारिश करूँगा (यानी JDK + OS + डिस्क, आदि की निगरानी के लिए) - कुछ नेटवर्क निगरानी प्रणाली का उपयोग - Nagios, Verax NMS या OpenNMS।


2
उसका रिसाव ऑफ-हीप है, इसलिए जेपीप्रोइलर वास्तव में यहाँ मदद नहीं करेगा
आसफ मेसिका

2

समस्या ढेर के बाहर है, इसलिए सबसे अच्छे उम्मीदवार हैं:

JNI leak  
Allocation of direct memory buffer

इस तथ्य के कारण कि आपने प्रत्यक्ष बफर आकार को सीमित कर दिया है, मेरी राय में सबसे अच्छा उम्मीदवार जेएनआई रिसाव है।


1

JDK में शामिल ढेर मेमोरी के आवंटन को देखने के लिए एक आसान उपकरण है, जिसे jmap कहा जाता है, इसके ऊपर आपके पास स्टैक आदि (Xss) भी हैं। स्मृति उपयोग के बारे में अधिक जानकारी प्राप्त करने के लिए इन दो जम्प कमांड को चलाएं:

jmap -heap <PID>
jmap -permstat <PID>

और भी अधिक जानकारी प्राप्त करने के लिए आप प्रक्रिया को जोंकॉल (JDK में शामिल) के साथ जोड़ सकते हैं। हालांकि Jconsole आवेदन में कॉन्फ़िगर किए जाने वाले JMX को फिर से बनाता है।


आपके उत्तर के लिए धन्यवाद, लेकिन समस्या कहीं बाहर ढेर की तरह लग रहा है। मैं
कॉन्स्टेंटिन एस।

प्रक्रिया के कितने सूत्र हैं? अधिकांश प्लेटफार्मों पर स्टैक का आकार 2 एमबी डिफ़ॉल्ट है, इसलिए थ्रेड्स की संख्या के साथ गुणा करें। मुझे आश्चर्य होगा अगर यह सभी "लापता" मेमोरी के लिए खाता है, लेकिन संभवतः इसमें से कुछ।
हम्पसलाई

लगभग 300 धागे, pmap से ली गई जानकारी में हमने 1Mb का स्टैक साइज है। और उसी pmap आउटपुट से यह नहीं दिखता है कि उनमें से कोई भी स्टैक 100Kb से अधिक का उपयोग करता है
Konstantin S.

0

JVisualVM का उपयोग करें। इसके पास कई अलग-अलग विचार हैं जो आपको बताएंगे कि मेमोरी कितने उपयोग में है, पर्मगेन इत्यादि।

अपने प्रश्न का उत्तर देने के लिए। जावा मेमोरी को अलग तरह से संभालता है जो आप उम्मीद कर सकते हैं।

जब आप -Xms और -Xmx पैरामीटर्स सेट करते हैं, तो आप JVM को बता रहे हैं कि इसे शुरू करने के लिए ढेर में कितनी मेमोरी आवंटित करनी चाहिए और अधिकतम के रूप में इसे कितना आवंटित करना चाहिए।

यदि आपके पास एक जावा एप्लिकेशन है जो कुल 1 मी मेमोरी का उपयोग करता है, लेकिन -Xms256m -Xmx2g में उत्तीर्ण होता है, तो JVM खुद को उपयोग किए गए 256m मेमोरी के साथ आरंभ करेगा। इससे कम का उपयोग नहीं होगा। इससे कोई फर्क नहीं पड़ता कि आपका एप्लिकेशन केवल 1m मेमोरी का उपयोग करता है।

दूसरी बात। उपरोक्त मामले में, यदि आप किसी बिंदु पर ऐप्प 256 एमबी से अधिक मेमोरी का उपयोग करते हैं, तो जेवीएम अनुरोध को सेवा देने के लिए जितनी आवश्यक हो उतनी मेमोरी आवंटित करेगा। हालांकि, यह ढेर के आकार को न्यूनतम मूल्य तक वापस नहीं लाएगा। कम से कम, अधिकांश परिस्थितियों में नहीं।

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.