2010-01-20 11 views
7

मैंने सी में एक पुस्तकालय लिखा है जो बहुत सारी स्मृति (लाखों छोटे ब्लॉक) का उपभोग करता है। मैंने एक सी प्रोग्राम लिखा है जो इस पुस्तकालय का उपयोग करता है। और मैंने एक जावा प्रोग्राम लिखा है जो एक ही पुस्तकालय का उपयोग करता है। जावा प्रोग्राम पुस्तकालय के चारों ओर एक बहुत ही पतली परत है। असल में केवल एक मूल विधि है जिसे बुलाया जाता है, क्या सभी काम करता है और बाद में घंटे लौटाता है। जावा इनवोकेशन इंटरफेस का उपयोग कर जावा और मूल पुस्तकालय के बीच कोई और संचार नहीं है। न ही जावा ऑब्जेक्ट है जो स्मृति की उल्लेखनीय मात्रा का उपभोग करता है।जावा द्वारा उपयोग किए जाने पर मूल पुस्तकालय 1.5 गुना अधिक स्मृति का उपयोग क्यों करता है जब लिनक्स के तहत सी-प्रोग्राम द्वारा उपयोग किया जाता है?

तो सी प्रोग्राम और जावा प्रोग्राम बहुत समान हैं। संपूर्ण गणना/स्मृति आवंटन मूल पुस्तकालय के अंदर होता है। फिर भी। जब सी प्रोग्राम निष्पादित किया गया तो 3 जीबी मेमोरी खपत होती है। लेकिन जावा प्रोग्राम 4.3 जीबी का उपभोग करता है! (शीर्ष पर रिपोर्ट की गई वीआईआरटी राशि)

मैंने जावा प्रक्रिया के मेमोरी मानचित्र (pmap का उपयोग करके) की जांच की। पुस्तकालयों द्वारा केवल 40 एमबी का उपयोग किया जाता है। तो जावा द्वारा लोड अतिरिक्त पुस्तकालय कारण नहीं हैं।

क्या किसी के पास इस व्यवहार के लिए कोई स्पष्टीकरण है?

संपादित करें: अभी तक उत्तर के लिए धन्यवाद। इसे थोड़ा और स्पष्ट बनाने के लिए: जावा कोड कुछ भी नहीं करता है लेकिन मूल पुस्तकालय ONCE पर आक्रमण करता है! जावा ढेर मानक आकार (शायद 60 एमबी) है और इसका उपयोग नहीं किया जाता है (एक वर्ग को छोड़कर मुख्य विधि और दूसरी कक्षा मूल पुस्तकालय का आह्वान करती है)।

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

+0

लिए intresting अवलोकन: मैं इसे openjdk के स्रोत कोड (arguments.cpp) को देख पाया। मैं इस व्यवहार की उम्मीद नहीं करता। – x4u

+0

मॉलोक ढेर विखंडन। Http://stackoverflow.com/a/28935176/166062 –

+0

@LariHotari देखें, जबकि इस प्रश्न का कारण एक अलग था (मेरा जवाब देखें), हमें वास्तव में विखंडन के साथ भी समस्याएं थीं। हमने इसे वैकल्पिक कार्यान्वयन जैसे टीसीएमएलओसी, जेमलोक या लॉकलेसिंक से मॉलोक कार्यान्वयन पर स्विच करके हल किया। –

उत्तर

2

क्षमा करें दोस्तों। गलत मान्यताओं।

मुझे 64 एमबी सूर्य जावा कार्यान्वयन का उपयोग किया गया जो डिफ़ॉल्ट अधिकतम ढेर आकार के लिए उपयोग किया जाता था। लेकिन मैंने परीक्षण के लिए openjdk 1.6 का उपयोग किया। ओपनजेडके भौतिक स्मृति के एक अंश का उपयोग करता है यदि अधिकतम ढेर आकार स्पष्ट रूप से निर्दिष्ट नहीं किया गया था। मेरे मामले में एक चौथाई। मैंने 4 जीबी मशीन का इस्तेमाल किया। एक चौथाई इस प्रकार 1 जीबी है। सी और जावा के बीच यह अंतर है।

अफसोस की बात यह व्यवहार कहीं भी दस्तावेज नहीं है।

// If the maximum heap size has not been set with -Xmx, 
// then set it as fraction of the size of physical memory, 
// respecting the maximum and minimum sizes of the heap. 
0

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

उम्मीद है कि यह मदद करता है, सर्वश्रेष्ठ संबंध, टॉम।

3

बस अनुमान लगाया जा रहा है: आप JVM के specfic जरूरतों के अनुरूप JVM के अंदर चलते समय गैर-डिफ़ॉल्ट malloc कार्यान्वयन का उपयोग कर रहे हैं और आपके सामान्य libc कार्यान्वयन में सामान्य उद्देश्य malloc से अधिक ओवरहेड उत्पन्न कर सकते हैं।

+0

यह मेरा अनुमान भी होगा। लेकिन मैं आपको तब तक +1 नहीं दे रहा हूं जब तक सबूत न हो कि वास्तव में मामला है। J12 द्वारा बुलाए गए – Omnifarious

1

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

+0

पुस्तकालय अभी भी आवंटित स्मृति को मुक्त कर सकते हैं। –

+0

एक संभावना यह है कि जावा थ्रेड देशी कोड के साथ एक साथ चल रहा है और वे स्मृति को खंडित कर रहे हैं। ओपी का कहना है कि बहुत सारे छोटे आवंटन हैं। – Omnifarious

+0

जावा के लिए अधिकतम ढेर आकार 60 एमबी या उससे भी कम है। यह 1 जीबी अधिक मेमोरी लेने का कारण नहीं हो सकता है। फिर भी: सी प्रोग्राम की तरह निवासी स्मृति 3 जीबी है। –

0

यह कहना मुश्किल है, लेकिन मुझे लगता है कि समस्या के दिल में यह है कि आपके आवेदन में दो ढेर हैं जिन्हें बनाए रखने की आवश्यकता है - जावा ऑब्जेक्ट आवंटन (जेवीएम द्वारा बनाए रखा गया) के लिए मानक जावा ढेर, और सी ढेर जिसे मॉलोक/फ्री पर कॉल द्वारा बनाए रखा जाता है। यह कहना मुश्किल है कि कुछ कोड देखे बिना क्या चल रहा है।

0

यहां मुकाबला करने के लिए एक सुझाव दिया गया है।

सी कोड मानक malloc कॉल का उपयोग कर बंद करो, और mmap ing /dev/zero द्वारा कि स्मृति पकड़ लेता है malloc का एक वैकल्पिक संस्करण का उपयोग करें। यदि आप ऐसा करने के लिए पर्याप्त सक्षम महसूस करते हैं तो आप या तो लाइब्रेरी से मॉलोक के कार्यान्वयन को संशोधित कर सकते हैं या अपना खुद का रोल कर सकते हैं।

मुझे दृढ़ता से संदेह है कि आप पाएंगे कि ऐसा करने के बाद आपकी समस्या दूर हो गई है।

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

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