मेमोरी उपयोग का विश्लेषण: जावा बनाम सी ++ नगण्य?


9

जावा में लिखे गए पूर्णांक ऑब्जेक्ट की मेमोरी का उपयोग C ++ में लिखे गए पूर्णांक ऑब्जेक्ट की मेमोरी उपयोग के साथ तुलना कैसे करता है? क्या अंतर नगण्य है? कोई फर्क नहीं? काफी बड़ा अंतर? मैं यह अनुमान लगा रहा हूं कि भाषा की परवाह किए बिना एक int एक int है?

मैंने ऐसा क्यों पूछा इसका कारण यह है कि मैं यह जानने के महत्व के बारे में पढ़ रहा था कि किसी प्रोग्राम की मेमोरी आवश्यकताएं प्रोग्रामर को दी गई समस्या को हल करने से कैसे रोकेंगी।

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

  • अपने अंतर उदाहरण चर के लिए 4 बाइट्स
  • ओवरहेड के 16 बाइट्स (ऑब्जेक्ट की कक्षा के संदर्भ में, कचरा संग्रहण जानकारी और सिंक्रनाइज़ेशन जानकारी)
  • पैडिंग के 4 बाइट्स

एक अन्य उदाहरण के रूप में, एक जावा सरणी (जिसे एक ऑब्जेक्ट के रूप में लागू किया जाता है) के लिए 48 + बाइट्स की आवश्यकता होती है:

  • हेडर जानकारी के 24 बाइट्स
  • ऑब्जेक्ट ओवरहेड के 16 बाइट्स
  • लंबाई के लिए 4 बाइट्स
  • पैडिंग के लिए 4 बाइट्स
  • साथ ही मूल्यों को संग्रहीत करने के लिए आवश्यक मेमोरी

C ++ में लिखे गए समान कोड के साथ ये मेमोरी usages की तुलना कैसे करते हैं?

मैंने जो C ++ और Java प्रोग्राम लिखे थे, उनके मेमोरी उपयोग के बारे में मैं अनजान था, लेकिन अब जब मैं एल्गोरिदम के बारे में जानने लगा हूं, तो मुझे कंप्यूटर के संसाधनों के लिए अधिक सराहना मिल रही है।


6
C ++ में "पूर्णांक वस्तु" क्या है? int? यदि हां, तो आपको इसकी तुलना intजावा में करनी चाहिए , तब तक नहीं Integer- जब तक कि आपका C ++ इन्टर्ब 32बिट्स नहीं हो जाता।
Mat

+1 अगर मैंने एक c ++ क्लास बनाई है जिसमें केवल एक ही इंट वेरिएबल था, तो उसे तुरंत बदल दिया
Anthony

3
a int एक int नहीं है - यह प्लेटफ़ॉर्म पर निर्भर है

1
केवल एक int सदस्य के साथ C ++ में आमतौर पर कोई ओवरहेड नहीं होगा। यह ठीक उसी जगह का उपयोग करेगा जितना कि प्लेट एक इंट को स्टोर करने के लिए उपयोग करता है (आमतौर पर वर्तमान पीसी प्लेटफार्मों पर 4 बाइट्स)।
डिर्क होलसॉपल

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

जवाबों:


15

यह प्लेटफॉर्म और कार्यान्वयन पर निर्भर करता है।

C ++ गारंटी देता है कि इसका आकार charबिल्कुल एक बाइट है और कम से कम 8 बिट चौड़ा है। फिर, एक short intका आकार कम से कम 16 बिट्स है और इससे छोटा नहीं है char। A का आकार intकम से कम आकार जितना बड़ा है short int। आकार long intकम से कम 32 बिट्स है और इंट से छोटा नहीं है।

sizeof(char) == 1; sizeof(long int) >= sizeof(int) >= sizeof(short int) >= sizeof(bool) >= sizeof(char).

C ++ का वास्तविक मेमोरी मॉडल बहुत ही कॉम्पैक्ट और प्रेडिक्टेबल है। उदाहरण के लिए वस्तुओं, सरणियों या बिंदुओं में कोई मेटाडेटा नहीं है। संरचनाएं और कक्षाएं सरणियों की तरह ही सन्निहित हैं, लेकिन जहां आवश्यक और आवश्यक हो वहां पैडिंग रखी जा सकती है।

सच कहूँ तो, इस तरह की तुलना मूर्खतापूर्ण है क्योंकि जावा मेमोरी उपयोग जावा कार्यान्वयन पर अधिक निर्भर करता है क्योंकि यह उस कोड पर चलता है।


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

ओपी पर ध्यान दें: आप अपने आप को पूर्णांक का आकार चुनने से बेहतर हो सकते हैं - यदि आप सी ++ में 32-बिट इंट चाहते हैं, तो आप उपयोग कर सकते हैं int32_t
केटीफ

9

अधिकांश उत्तर कुछ प्रमुख बिंदुओं को नजरअंदाज करते हुए प्रतीत होते हैं।

सबसे पहले, जावा के एक भयानक बहुत में, आप वास्तव में कभी भी एक कच्चा नहीं देखते हैं int- लगभग सभी का उपयोग होता है Integer, इसलिए तथ्य यह है कि सी या सी ++ में intएक ही आकार का (लगभग) लगभग अप्रासंगिक हो सकता है, इसके अलावा ( मेरे अनुभव में, कोड का छोटा) प्रतिशत जो केवल के बजाय उपयोग करता है ।intintInteger

दूसरे, व्यक्तिगत वस्तुओं के आकार का पूरे कार्यक्रम के मेमोरी फुटप्रिंट से लगभग कोई लेना-देना नहीं है। जावा में, प्रोग्राम की मेमोरी फ़ुटप्रिंट मुख्य रूप से संबंधित है कि कचरा कलेक्टर को कैसे ट्यून किया गया है। ज्यादातर मामलों में, GC को गति को अधिकतम करने के लिए ट्यून किया जाता है, जो (बड़े पैमाने पर) का अर्थ है कि जीसी को यथासंभव अधिक से अधिक चलाना।

मेरे पास इस समय एक लिंक काम नहीं है, लेकिन कुछ परीक्षण दिखा रहे हैं कि जावा सी के समान गति के आसपास चल सकता है, लेकिन ऐसा करने के लिए आपको जीसी को शायद ही कभी चलाना होगा, जो लगभग 7 गुना अधिक उपयोग करता है याद। ऐसा इसलिए नहीं है क्योंकि व्यक्तिगत वस्तुएं 7 गुना बड़ी हैं, लेकिन अगर आप इसे बहुत बार करते हैं तो जीसी काफी महंगा हो सकता है। इससे भी बदतर, जीसी केवल मेमोरी जारी कर सकता है जब यह "साबित" कर सकता है कि किसी वस्तु तक पहुंचने का कोई तरीका नहीं है, बल्कि जब आप जानते हैं कि आप इसका उपयोग कर रहे हैं। इसका मतलब यह है कि भले ही आप मेमोरी उपयोग को कम करने के लिए जीसी को अधिक बार चलाते हैं, आप शायद एक विशिष्ट कार्यक्रम पर योजना बना सकते हैं जिसमें एक मेमोरी फ़ुटप्रिंट होता है जो बड़ा होता है। इस तरह एक मामले में, आप कारक को 2 के बजाय 2 या 3 तक कम कर सकते हैं। भले ही आप अत्यधिक ओवरबोर्ड पर जाएं, हालांकि, डॉन1 है

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


1 यह कहना नहीं है कि कोई भी संभवतः जावा को एक पदचिह्न के साथ लिखने का प्रबंधन नहीं कर सकता है जो आपके पास सी ++ के साथ मिल जाएगा। यह केवल कि कहने के लिए है सिर्फ वस्तुओं के एक ही नंबर / आकार वाले, और जीसी वास्तव में अक्सर चल आप एक नियम के रूप में वहाँ नहीं मिलेगा।


7
आपके पहले बिंदु के बारे में: मैं कोई जावा लड़का नहीं हूं, लेकिन मैंने जो जावा एपीआई देखा है, उसका इस्तेमाल कभी नहीं किया है Integer(वे क्यों?) int। केवल सामान्य संग्रह के पास Integerटाइप इरेज़र के कारण उपयोग करने के अलावा कोई विकल्प नहीं होता है , लेकिन अगर आप ध्यान दें कि आप उन कार्यान्वयन को बदल सकते हैं जिन्हें विशेष रूप से intया जो भी आदिम प्रकार की ज़रूरत हो, उन्हें लागू कर सकते हैं । और फिर जेनेरिक रैपिंग कोड (जैसे सब कुछ जिसकी आवश्यकता है Object[]) से गुजरने के लिए अस्थायी बॉक्सिंग है । इसके अलावा, क्या आपके पास जीसी स्पेस ओवरहेड के लिए स्रोत हैं? मुझे वास्तव में संदेह नहीं है, मैं केवल उत्सुक हूं।


9

मुझे आशा है कि आपको एहसास होगा कि यह सब जावा और सी ++ दोनों के लिए गहराई से कार्यान्वयन-परिभाषित है। कहा जा रहा है कि, जावा के ऑब्जेक्ट मॉडल के लिए काफी कम जगह की आवश्यकता होती है।

C ++ ऑब्जेक्ट्स को सदस्यों की आवश्यकता के अलावा किसी भी भंडारण की आवश्यकता नहीं होती है। ध्यान दें कि (जावा के विपरीत, जहां उपयोगकर्ता द्वारा परिभाषित सब कुछ एक संदर्भ प्रकार है), क्लाइंट कोड किसी ऑब्जेक्ट का उपयोग मान प्रकार या संदर्भ प्रकार दोनों के रूप में कर सकता है, अर्थात कोई ऑब्जेक्ट किसी अन्य ऑब्जेक्ट के लिए पॉइंटर / संदर्भ स्टोर कर सकता है या ऑब्जेक्ट को सीधे स्टोर कर सकता है अप्रत्यक्ष के बिना। यदि कोई virtualविधियाँ हैं, तो प्रति ऑब्जेक्ट एक अतिरिक्त पॉइंटर आवश्यक है , लेकिन पॉलीमोर्फिज़्म के बिना प्राप्त करने के लिए काफी उपयोगी कक्षाएं डिज़ाइन की गई हैं और इसकी आवश्यकता नहीं है। कोई GC मेटाडेटा और कोई प्रति-ऑब्जेक्ट लॉक नहीं है। इस प्रकार class IntWrapper { int x; public: IntWrapper(int); ... };वस्तुओं को प्लेन intएस की तुलना में अधिक जगह की आवश्यकता नहीं होती है , और संग्रह और अन्य वस्तुओं में सीधे (अर्थात अप्रत्यक्ष रूप से बिना) रखा जा सकता है।

Arrays मुश्किल है क्योंकि कोई पूर्व-निर्मित नहीं है, C ++ में जावा ऐरे के बराबर आम है। आप बस के साथ वस्तुओं का एक गुच्छा आवंटित कर सकते हैं new[](बिल्कुल नहीं ओवरहेड / मेटाडेटा के साथ) लेकिन कोई लंबाई फ़ील्ड नहीं है - कार्यान्वयन शायद एक को संग्रहीत करता है लेकिन आप इसे एक्सेस नहीं कर सकते। std::vectorएक गतिशील सरणी है और इस प्रकार अतिरिक्त ओवरहेड और बड़ा इंटरफ़ेस है। std::arrayऔर सी-स्टाइल सरणियाँ (int arr[N];), एक संकलन-समय स्थिर की जरूरत है। सिद्धांत रूप में, यह सिर्फ ऑब्जेक्ट का स्टोरेज और लंबाई के लिए एक ही पूर्णांक होना चाहिए - लेकिन चूंकि आप गतिशील आकार परिवर्तन प्राप्त कर सकते हैं और बहुत कम अतिरिक्त स्थान के साथ पूरी तरह से चित्रित इंटरफ़ेस, आप बस उस अभ्यास के लिए जाते हैं। ध्यान दें कि ये सभी, साथ ही अन्य सभी संग्रह, वस्तुओं को मूल्य द्वारा संग्रहीत करने के लिए डिफ़ॉल्ट हैं, इस प्रकार आपको अप्रत्यक्ष और संदर्भों के लिए जगह की बचत होती है, और कैश व्यवहार में सुधार होता है। अप्रत्यक्ष रूप से प्राप्त करने के लिए आपको स्पष्ट रूप से पॉइंटर्स (स्मार्ट वाले, कृपया) स्टोर करना होगा।

उपरोक्त तुलना पूरी तरह से उचित नहीं है, क्योंकि इनमें से कुछ बचतों को जावा की विशेषताओं को शामिल नहीं करके खर्च किया जाता है, और उनके सी ++ समकक्ष को अक्सर जावा समकक्ष (*) की तुलना में कम अनुकूलित किया जाता है। आम तरीका लागू करने के लिए virtualवास्तव में आम तरीका लागू करने के लिए के रूप में ज्यादा भूमि के ऊपर के रूप में सी ++ लगाता में virtualजावा में। लॉक प्राप्त करने के लिए, आपको पूरी तरह से म्यूटेक्स ऑब्जेक्ट की आवश्यकता होती है, जो कि कुछ बिट्स की तुलना में सबसे अधिक संभावना है। संदर्भ गिनती प्राप्त करने के लिए ( नहींजीसी के बराबर, और इस तरह के रूप में इस्तेमाल नहीं किया जाना चाहिए, लेकिन कभी-कभी उपयोगी), आपको एक स्मार्ट पॉइंटर की आवश्यकता होती है जो एक संदर्भ गणना फ़ील्ड जोड़ता है। जब तक कि वस्तु का सावधानीपूर्वक निर्माण नहीं किया जाता है, संदर्भ गणना, स्मार्ट पॉइंटर ऑब्जेक्ट, और संदर्भित ऑब्जेक्ट पूरी तरह से अलग स्थानों पर होते हैं, और जब आप इसे सही तरीके से बनाते हैं, तब भी साझा किए गए पॉइंटर (एक?) के बजाय दो बिंदु हो सकते हैं। फिर, अच्छी सी ++ शैली इन विशेषताओं का उपयोग करने के लिए पर्याप्त नहीं है यह बात करने के लिए - व्यवहार में, एक अच्छी तरह से लिखा सी ++ लाइब्रेरी की वस्तुएं कम उपयोग करती हैं। यह जरूरी नहीं कि समग्र रूप से कम मेमोरी उपयोग का मतलब है, लेकिन इसका मतलब यह है कि इस संबंध में सी ++ की अच्छी शुरुआत है।

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


3

intजावा में एक सादा , intसी ++ में बिल्कुल जगह लेता है , बशर्ते कि दोनों कार्यान्वयन समान पूर्णांक आकार और मेमोरी संरेखण का उपयोग करें।

एक int 'ऑब्जेक्ट' (एक बॉक्सर पूर्णांक, जो कि एक श्रेणी का उदाहरण है Integer), जावा में वर्ग उदाहरण के सभी ओवरहेड को वहन करता है, इसलिए यह intC ++ की तुलना में काफी बड़ा है । हालाँकि, यदि आप C ++ में किसी ऑब्जेक्ट को उसी फीचर्स से लैस करना चाहते थे, जिसमें जावा ऑब्जेक्ट्स आउट-ऑफ-द-बॉक्स (पॉलीमॉर्फिज्म, बॉक्सिंग, गारबेज कलेक्शन, आरटीटीआई) के साथ आते हैं, तो आप संभवतः समान ऑब्जेक्ट के साथ समाप्त करेंगे आकार।

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

हां, जावा ऑब्जेक्ट सी ++ कक्षाओं की तुलना में डिफ़ॉल्ट रूप से अधिक ओवरहेड ले जाता है, लेकिन वे अधिक सुविधाओं के साथ आते हैं, और यह एक अलग प्रोग्रामिंग शैली की ओर जाता है - एक अच्छा प्रोग्रामर किसी भी भाषा के ऊपर और नीचे का लाभ उठा सकता है।


+1 अधिक ओवरहेड लेकिन जावा में अधिक सुविधाएँ, मुझे अब समझ में आया, धन्यवाद
एंथनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.