क्या हमें जावा में ऑब्जेक्ट निर्माण से बचना चाहिए?


242

मुझे एक सहकर्मी ने बताया था कि जावा ऑब्जेक्ट निर्माण सबसे महंगा ऑपरेशन है जिसे आप कर सकते हैं। इसलिए मैं केवल कुछ वस्तुओं को यथासंभव बनाने के लिए निष्कर्ष निकाल सकता हूं।

यह वस्तु उन्मुख प्रोग्रामिंग के उद्देश्य को हराने के लिए कुछ हद तक लगता है। यदि हम वस्तुओं का निर्माण नहीं कर रहे हैं, तो हम अनुकूलन के लिए सिर्फ एक लंबी कक्षा सी शैली लिख रहे हैं?


39
"जावा ऑब्जेक्ट निर्माण सबसे महंगा ऑपरेशन है जो आप कर सकते हैं" । उस दावे के स्रोत को साझा करने का मन?
सोंगो

92
और - क्या की तुलना में सबसे महंगा ऑपरेशन? एक अंक बढ़ाने के लिए 900 अंकों की तुलना में पीआई की गणना या एक इंट्रीमेंट की तुलना में?
जोंकों

4
हो सकता है कि वे उस विशिष्ट वस्तु निर्माण के किसी विशेष भाग के बारे में बात कर रहे हों? मैं सोच रहा हूँ कि Apple tableViewCells के लिए एक कतार का उपयोग कैसे करता है। शायद आपका सहयोगी कुछ वस्तुओं को बनाने और उन विशिष्ट वस्तुओं से जुड़े कुछ ओवरहेड के कारण उनका पुन: उपयोग करने का सुझाव दे रहा था? बस यह पता लगाने की कोशिश की जा रही है कि वे ऐसा दावा क्यों करेंगे।
टायलर डेविट

3
यह सबसे मजेदार चीजों में से एक है जिसे मैंने प्रोग्रामिंग के बारे में कभी सुना है।)
मर्ट अक्काया

22
अरिथमेटिक काफी महंगा भी है; हमें गणना से बचना चाहिए, ओह, और एक जेवीएम शुरू करना वास्तव में महंगा है इसलिए हमें किसी भी जेवीएम को शुरू नहीं करना चाहिए :-)।
जेम्स एंडरसन

जवाबों:


478

आपके सहकर्मी को पता नहीं है कि वे किस बारे में बात कर रहे हैं।

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

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

सब कुछ एक वस्तु है (को छोड़कर primitives)

आदिम ( int, long, double, आदि) के अलावा सभी चीजें जावा में ऑब्जेक्ट हैं। जावा में ऑब्जेक्ट निर्माण से बचने का कोई तरीका नहीं है।

अपनी मेमोरी आवंटन रणनीतियों के कारण जावा में ऑब्जेक्ट निर्माण ज्यादातर मामलों में C ++ से तेज है और JVM में बाकी सभी चीजों की तुलना में सभी व्यावहारिक उद्देश्यों के लिए "मुक्त" माना जा सकता है

1990 की शुरुआत में 2000 के दशक के प्रारंभ में जेवीएम कार्यान्वयन ने वस्तुओं के वास्तविक आवंटन में कुछ प्रदर्शन किया था। यह कम से कम 2005 के बाद से ऐसा नहीं है।

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

यह कोशिश नहीं करता है और मुक्त स्थान को अधिकतम करता है, जो वैसे भी एक लाल हेरिंग है, यह रनटाइम के प्रदर्शन को अधिकतम करता है। अगर इसका मतलब है कि JVM हीप हर समय लगभग 100% आवंटित किया जाता है, तो ऐसा ही हो। JVM हीप मेमोरी आपको वैसे भी वहां बैठने के लिए कुछ भी नहीं देती है।

एक गलत धारणा है कि जीसी मेमोरी को एक उपयोगी तरीके से बाकी सिस्टम में वापस कर देगा, यह पूरी तरह से गलत है!

JVM ढेर हो जाना और इतने हटना है कि प्रणाली के बाकी हिस्सों सकारात्मक मुक्त स्मृति से प्रभावित होता है नहीं है JVM ढेर में-Xmsस्टार्टअप में निर्दिष्ट सभी को आवंटित करता है और इसका अनुमान कभी भी उस मेमोरी को ओएस पर वापस जारी करने के लिए किसी भी अन्य ओएस प्रक्रियाओं के साथ साझा नहीं किया जाता है जब तक कि जेवीएम का उदाहरण पूरी तरह से समाप्त नहीं हो जाता। -Xms=1GB -Xmx=1GBकिसी भी समय वास्तव में कितने ऑब्जेक्ट बनाए जाते हैं, इसकी परवाह किए बिना 1GB RAM आवंटित करता है। कुछ सेटिंग्स हैं जो ढेर मेमोरी के प्रतिशत को जारी करने की अनुमति देती हैं, लेकिन सभी व्यावहारिक उद्देश्यों के लिए जेवीएम कभी भी इस मेमोरी को पर्याप्त रूप से जारी करने में सक्षम नहीं होता है।इसलिए कोई अन्य प्रक्रिया इस मेमोरी को पुनः प्राप्त नहीं कर सकती है, इसलिए जेवीएम हीप के मुक्त होने से बाकी सिस्टम को कोई लाभ नहीं होता है। इसके लिए एक RFE 29-NOV-2006 को "स्वीकार" किया गया था , लेकिन इसके बारे में कभी कुछ नहीं किया गया। यह व्यवहार अधिकार के किसी भी व्यक्ति द्वारा एक चिंता नहीं माना जाता है।

एक गलत धारणा है कि कई छोटी छोटी जीवित वस्तुओं को बनाने से जेवीएम लंबे समय तक रुकने का कारण बनता है, यह अब अच्छी तरह से गलत है

वर्तमान जीसी एल्गोरिदम वास्तव में कई छोटी वस्तुओं को बनाने के लिए अनुकूलित हैं जो अल्पकालिक हैं, जो कि मूल रूप से हर कार्यक्रम में जावा वस्तुओं के लिए 99% अनुमानी है। ऑब्जेक्ट पूलिंग के प्रयास वास्तव में ज्यादातर मामलों में JVM का प्रदर्शन खराब कर देंगे।

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

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

ऑब्जेक्ट ओरिएंटेड डायनेमिक भाषाएं संवेदनशील संवेदनशील परीक्षणों पर अब भी दिनों सी की पिटाई कर रही हैं।


274
+1: "आपका सबसे महंगा ऑपरेशन उनकी बात सुन रहा होगा ..."। सबसे अच्छा मैंने कुछ समय के लिए सुना है।
rjnilsson

21
@DeadMG, संचयी GC ओवरहेड के साथ भी, जावा C ++ से अधिक तेज हो सकता है (जैसे, ढेर संकलन के कारण, कुछ डेटा संरचनाओं के लिए कैश मिस को कम करना)।
एसके-तर्क

13
@ एसके-तर्क: जैसा कि जीसी गैर-नियतात्मक है, वास्तव में यह साबित करना बहुत मुश्किल है। कैश की कमी को कम करने के लिए, यह करना मुश्किल है कि जब प्रत्येक वस्तु को एक अन्य अप्रत्यक्ष होना चाहिए, तो कैश स्थान को बर्बाद करना और निष्पादन समय बढ़ाना होगा। हालांकि, मैं तर्क देता हूं कि ऑब्जेक्ट पूल या मेमोरी एरेना जैसे सी ++ में एक उपयुक्त एलोकेटर का उपयोग करके, आप आसानी से कचरा कलेक्टर के प्रदर्शन को मैच या हरा सकते हैं। उदाहरण के लिए, आप एक मेमोरी एरेना क्लास लिख सकते हैं जो कि _allocaएमॉर्टाइज़्ड की तुलना में तेज़ी से प्रदर्शन करेगा ।
डेडएमजी

33
ऑब्जेक्ट क्रिएशन अब पहले की तुलना में सस्ता है। हालांकि यह मुफ़्त नहीं है। जो भी तुमसे कहता है कि झूठ बोल रहा है। और सी को पीटने वाली ओओ भाषाओं के बारे में लिंक किसी के लिए अतिरंजित प्रतिक्रिया है जो वास्तव में सीखने की कोशिश कर रहा है।
जोंकों

17
यह इस तरह के उत्तरों के कारण है कि हम भद्दे कोड के साथ समाप्त होते हैं। सही उत्तर जावा में एक ऑब्जेक्ट बना रहा है, दोनों जावा ऑब्जेक्ट बना रहा है और इसे इनिशियलाइज़ कर रहा है। पहला हिस्सा सस्ता है, दूसरा बहुत महंगा हो सकता है। newहॉटस्पॉट स्थान में कीवर्ड का उपयोग करने से पहले लोगों को हमेशा देखना चाहिए कि कंस्ट्रक्टरों में क्या होता है। मैंने देखा है कि लोग स्विंगिंग ऑब्जेक्ट new ImageIcon(Image)की paint()विधि का उपयोग करते हैं, जो बहुत महंगा है और पूरे यूआई को सुपर सुस्त बना रहा है। तो यह एक काले और सफेद जवाब नहीं है, इससे पहले कि आप newकहीं का उपयोग करें ।
qwertzguy

94

नीचे पंक्ति: ऑब्जेक्ट्स बनाने के शॉर्टकट लेने के लिए अपने डिज़ाइन से समझौता न करें। अनावश्यक रूप से वस्तुओं को बनाने से बचें। यदि समझदार है, तो अनावश्यक कार्यों से बचने के लिए डिजाइन (किसी भी प्रकार का)।

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

इससे पहले कि कोई इस मामले को किनारे कर दे - मेरे पास ऐसे एप्लिकेशन हैं, जिन्होंने ~ 50 पंक्तियों के डेटा को प्रोसेस करने के लिए 20 + MB ऑब्जेक्ट का अनुकूलन करने से पहले, अनुकूलित किया है। यह परीक्षण में ठीक है, जब तक कि आप एक मिनट में सौ अनुरोध नहीं करते हैं और अचानक आप प्रति मिनट 2GB डेटा बना रहे हैं। यदि आप 20 reqs / sec करना चाहते हैं तो आप 400MB ऑब्जेक्ट बना रहे हैं और फिर उसे फेंक रहे हैं। 20 reqs / sec एक सभ्य सर्वर के लिए छोटा है।


7
मैं एक उदाहरण जोड़ सकता हूं: कुछ मामलों में यह वास्तव में कोड की स्पष्टता के मामले में कोई फर्क नहीं पड़ता है, लेकिन प्रदर्शन में अधिक या कम बड़ा अंतर कर सकता है: जब धाराओं से पढ़ते हैं, उदाहरण के लिए, कुछ का उपयोग करना असामान्य नहीं है, while(something) { byte[] buffer = new byte[10240]; ... readIntoBuffer(buffer); ...जो हो सकता है जैसे की तुलना में बेकार हो byte[] buffer = new byte[10240]; while(something) { ... readIntoBuffer(buffer); ...
जिमीबी

4
+1: अनावश्यक वस्तु निर्माण (या हटाने के बाद सफाई) निश्चित रूप से कभी-कभी महंगा हो सकता है। जावा में 3 डी ग्राफिक्स / ओपनजीएल कोड एक जगह है जहां मैंने जीसी के बाद से बनाई गई वस्तुओं की संख्या को कम करने के लिए किए गए अनुकूलन को देखा है अन्यथा आपके फ्रामर्ट के साथ कहर बरपा सकता है।
सिंह

1
वाह! डेटा की 50 पंक्तियों को संसाधित करने के लिए 20+ एमबी? पागल लगता है। किसी भी मामले में, क्या वे वस्तुएं लंबे समय तक जीवित रहती हैं? क्योंकि यही वह मामला है जो GC के लिए मायने रखेगा। यदि दूसरी ओर आप केवल स्मृति आवश्यकताओं पर चर्चा कर रहे हैं , तो यह कचरा संग्रह या ऑब्जेक्ट निर्माण दक्षता से संबंधित नहीं है ...
एंड्रेस एफ

1
ऑब्जेक्ट अल्पकालिक (सामान्य मामले में 0.5 सेकेंड से कम) हैं। कचरे की वह मात्रा अभी भी प्रदर्शन को प्रभावित करती है।
जोंक

2
वास्तविकता पर दृढ़ता से खड़े रहने के लिए धन्यवाद, जो कोई भी एक विचारहीन वास्तुकला के प्रभाव के साथ रहता है वह बहुत संबंधित हो सकता है।
जेएम बेकर

60

दरअसल, स्मृति प्रबंधन रणनीतियों के कारण जो जावा भाषा (या कोई अन्य प्रबंधित भाषा) संभव बनाती है, ऑब्जेक्ट निर्माण युवा पीढ़ी नामक मेमोरी के एक ब्लॉक में एक सूचक को बढ़ाने से थोड़ा अधिक है। यह C से बहुत तेज़ है, जहाँ मुफ्त मेमोरी की खोज करनी होती है।

लागत का अन्य हिस्सा ऑब्जेक्ट विनाश है, लेकिन सी की तुलना करना कठिन है। एक संग्रह की लागत लंबी अवधि तक बचाई गई वस्तुओं की मात्रा पर आधारित है, लेकिन संग्रह की आवृत्ति बनाई गई वस्तुओं की मात्रा पर आधारित है ... में अंत में, यह अभी भी सी-स्टाइल मेमोरी प्रबंधन की तुलना में बहुत तेज है।


7
+1 भले ही कचरा कलेक्टर "बस काम करता है", प्रत्येक जावा प्रोग्रामर को जेनरल कचरा कलेक्टर के बारे में सीखना चाहिए।
बेंजोडा

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

4
भागने के विश्लेषण के लिए एक अगला चरण है , शुद्ध रूप से रजिस्टरों में छोटी वस्तु के लिए मेमोरी "आवंटित" करना (उदाहरण के लिए एक Pointवस्तु 2 सामान्य उद्देश्य रजिस्टरों में फिट हो सकती है)।
जोआचिम सॉयर

6
@ जोकिम सॉर: यह हॉटस्पॉट वीएम के नए कार्यान्वयन में किया जाता है। इसे स्केलर रिप्लेसमेंट कहा जाता है।
someguy

1
@someguy: मैंने इसके बारे में कुछ समय पहले अगली चीज़ के रूप में पढ़ा है, लेकिन यह जांचने के लिए अनुवर्ती नहीं था कि यह पहले से ही है। यह सुनना उत्कृष्ट खबर है कि हमारे पास पहले से ही यह है।
जोआचिम सॉयर

38

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

कर रहे हैं बहुत ही खास स्थितियों की एक जोड़ी जहां है है एक अच्छा विचार ऑब्जेक्ट निर्माण से बचने के लिए।

  • जब आप लेटेंसी-सेंसिटिव एप्लिकेशन लिख रहे हों और जीसी पॉज से बचना चाहते हैं। आप जितनी अधिक वस्तुओं का उत्पादन करते हैं, उतनी ही अधिक जीसी होती है और विराम की संभावना अधिक होती है। यह खेल, कुछ मीडिया अनुप्रयोगों, रोबोट नियंत्रण, उच्च-आवृत्ति ट्रेडिंग आदि के लिए प्रासंगिक के लिए एक वैध विचार हो सकता है। समाधान उन सभी वस्तुओं / सरणियों को पूर्व-आवंटित करना है, जिनकी आपको आवश्यकता है और उन्हें फिर से उपयोग करें। ऐसे पुस्तकालय हैं जो इस तरह की क्षमता प्रदान करने में विशेषज्ञ हैं, जैसे कि Javolution । लेकिन यकीनन, अगर आप वास्तव में कम विलंबता के बारे में परवाह करते हैं, तो आपको जावा या सी # के बजाय सी / सी ++ / कोडांतरक का उपयोग करना चाहिए।
  • कुछ परिस्थितियों में बॉक्सिंग प्राइमेटिव्स (डबल, इंटेगर आदि) से बचना एक बहुत ही लाभकारी सूक्ष्म अनुकूलन हो सकता है। चूंकि अनबॉक्सिड प्राइमिटिव (डबल, इंट आदि) प्रति-ऑब्जेक्ट ओवरहेड से बचते हैं, वे बहुत तेजी से सीपीयू गहन कार्य जैसे संख्यात्मक प्रसंस्करण आदि होते हैं। आमतौर पर, आदिम सरणियाँ जावा में बहुत अच्छा प्रदर्शन करती हैं, इसलिए आप इनका उपयोग अपने नंबर क्रंची के बजाय करना चाहते हैं। किसी भी अन्य प्रकार की वस्तुएं।
  • में विवश स्मृति स्थितियों आप में से (सक्रिय) संख्या को कम करने के लिए बनाया वस्तुओं चाहते हैं के बाद से प्रत्येक वस्तुओं एक छोटे से भूमि के ऊपर (JVM कार्यान्वयन के आधार पर आम तौर पर 8-16 बाइट्स) किया जाता है। ऐसी परिस्थितियों में आपको बड़ी संख्या में छोटी वस्तुओं के बजाय अपने डेटा को संग्रहीत करने के लिए बड़ी संख्या में बड़ी वस्तुओं या सरणियों को प्राथमिकता देना चाहिए।

3
यह ध्यान देने योग्य है कि बच विश्लेषण अल्पकालिक (बंधे हुए जीवन) वस्तुओं को ढेर पर संग्रहीत करने की अनुमति देगा, इन वस्तुओं को मुफ्त में ibm.com/developerworks/java/library/j-jtp09275-index.html
रिचर्ड टिंगल

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

2
इसके अलावा, 100% सही बच विश्लेषण हॉल्टिंग समस्या के बराबर है। जटिल परिस्थितियों में भागने के विश्लेषण पर भरोसा मत करो, क्योंकि यह कम से कम कुछ समय में गलत जवाब देने की संभावना है।
जूल्स

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

17

आपके सहकर्मी जो कह रहे हैं, उसमें सच्चाई का एक हिस्सा है। मैं सम्मानपूर्वक सुझाव देता हूं कि मुद्दा निर्माण वास्तव में कचरा संग्रह है । C ++ में प्रोग्रामर ठीक से नियंत्रित कर सकता है कि मेमोरी कैसे डील की जाती है। कार्यक्रम लंबे समय तक या जितना संभव हो उतना कम समय तक क्रूड जमा कर सकता है। इसके अलावा, C ++ प्रोग्राम क्रूड को एक अलग थ्रेड का उपयोग करके छोड़ सकता है, जिसने इसे बनाया था। इस प्रकार वर्तमान में काम कर रहे धागे को कभी भी साफ करने के लिए रोकना नहीं पड़ता है।

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

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

यह बात कब हो सकती है? किसी भी समय आप लगातार उप-मिलीसेकंड प्रतिक्रिया दरों के बारे में परवाह करते हैं, आप जीसी के बारे में ध्यान रखेंगे। जावा में लिखे गए स्वचालित ट्रेडिंग सिस्टम पॉज़ को कम करने के लिए जेवीएम को भारी बनाते हैं। ऐसी फर्में जो अन्यथा जावा को C ++ में उन स्थितियों में लिखती हैं, जहां सिस्टम को हर समय अत्यधिक संवेदनशील होना पड़ता है।

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


10
अधिकांश आधुनिक जेवीएम का समर्थन "दुनिया को रोकें" की तुलना में बेहतर कचरा संग्रह एल्गोरिदम है। कचरा संग्रह में बिताया गया अमूर्त समय, मालकॉक / मुफ्त में स्पष्ट रूप से खर्च करने की तुलना में अक्सर कम होता है। क्या C ++ मेमोरी मैनेजमेंट एक अलग थ्रेड में चलता है?

10
ओरेकल के नए जावा संस्करण विश्लेषण से बच सकते हैं, जिसका अर्थ है कि एक विधि से बचने वाली वस्तुएं स्टैक पर आवंटित नहीं की जाती हैं, जो उन्हें मुफ्त में साफ करती हैं - विधि के वापस आने पर वे स्वचालित रूप से निपट जाते हैं।
जेसपर

2
@ ThorbjørnRavnAndersen: वाक़ई? क्या आप वास्तव में विराम का मतलब है- कम GC, या क्या आप का अर्थ है "आमतौर पर समानांतर-लेकिन-कभी-कभी-एक-सा-थोड़ा-रुकने वाला" GC? मुझे समझ नहीं आ रहा है कि GC किस तरह एक कार्यक्रम को रोक नहीं सकता है, और फिर भी एक ही समय में वस्तुओं को इधर-उधर कर सकता है ... ऐसा लगता है, काफी शाब्दिक रूप से, मेरे लिए असंभव है ...
मेहरदाद

2
@ ThorbjørnRavnAndersen: यह "दुनिया को कैसे रोक सकता है" लेकिन कभी "जेवीएम को रोकें"? इसका कोई मतलब नहीं है ...
मेहरदाद

2
@ ThorbjørnRavnAndersen: नहीं, मैं वास्तव में नहीं; मुझे समझ में नहीं आ रहा है कि आप क्या कह रहे हैं। या तो जीसी कभी-कभी प्रोग्राम को रोक देता है, जिस स्थिति में यह है - परिभाषा के अनुसार - "पॉज़लेस" नहीं, या यह प्रोग्राम को कभी भी पॉज़ नहीं करता है (इसलिए, यह "पॉज़लेस" है), जिस स्थिति में मुझे समझ नहीं आता कि कैसे आपके "यह दुनिया को रोक देता है जब यह रख नहीं सकता है" से मेल खाती है, क्योंकि यह प्रतीत होता है कि जीसी चल रहा है, जबकि कार्यक्रम को रोक दिया गया है। क्या आप बताएंगे कि कौन सा मामला है (क्या यह रुका हुआ है या नहीं?), और यह कैसे संभव है?
मेहरदाद

11

एक ऐसा मामला है जहां आपको ओवरहेड के कारण जावा में बहुत अधिक ऑब्जेक्ट बनाने से हतोत्साहित किया जा सकता है - एंड्रॉइड प्लेटफॉर्म पर प्रदर्शन के लिए डिजाइन करना

इसके अलावा, उपरोक्त उत्तर सही हैं।


2
प्रश्न फिर से पढ़ें। यह टैग सहित कहीं भी जेवीएम को निर्दिष्ट नहीं करता है। इसमें केवल जावा का उल्लेख है।
पीटर केली

9

जीसी को कई छोटी जीवित वस्तुओं के लिए तैयार किया जाता है

कहा कि अगर आप तुच्छता से वस्तु आवंटन को कम कर सकते हैं, तो आपको करना चाहिए

एक उदाहरण एक पाश में एक स्ट्रिंग का निर्माण होगा, भोला तरीका होगा

String str = "";
while(someCondition){
    //...
    str+= appendingString;
}

जो Stringप्रत्येक +=ऑपरेशन पर एक नई वस्तु बनाता है (प्लस StringBuilderऔर एक नया अंतर्निहित चार सरणी)

आप इसमें आसानी से लिख सकते हैं:

StringBuilder strB = new StringBuilder();
while(someCondition){
    //...
    strB.append(appendingString);
}
String str = strB.toString();

इस पैटर्न (अपरिवर्तनीय परिणाम और एक स्थानीय परिवर्तनशील मध्यवर्ती मूल्य) को अन्य चीजों पर भी लागू किया जा सकता है

लेकिन इसके अलावा आपको भूतों का पीछा करने के बजाय असली अड़चन खोजने के लिए एक प्रोफाइलर को खींचना चाहिए


इस StringBuilderदृष्टिकोण में सबसे बड़ा लाभ पूर्व-आकार है StringBuilderताकि इसे कभी भी निर्माणकर्ता के साथ अंतर्निहित सरणी को फिर से स्थापित न करना पड़े StringBuilder(int)। यह आवंटन के बजाय एकल आवंटन बनाता है 1+N

2
@JarrodRoberson StringBuilder कम से कम वर्तमान क्षमता को दोगुना करेगी या दूसरे शब्दों में क्षमता केवल लॉग (n) आवंटन के लिए तेजी से बढ़ेगी
शाफ़्ट फ्रीक

6

जोशुआ बलोच (जावा प्लेटफ़ॉर्म रचनाकारों में से एक) ने 2001 में अपनी पुस्तक इफेक्टिव जावा में लिखा था:

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


1
यहां तक ​​कि नेटवर्क कनेक्शन जैसी चीजों के साथ, जो महत्वपूर्ण है वह है जीसी-आबंटित ऑब्जेक्ट्स को कनेक्शन से जुड़े बनाए रखना नहीं, बल्कि उन कनेक्शनों के सेट को बनाए रखना जो जीसी-प्रबंधित दुनिया के बाहर मौजूद हैं। ऐसे समय होते हैं जब पूलिंग ऑब्जेक्ट्स स्वयं सहायक हो सकते हैं; उन मामलों में से अधिकांश स्टेम जहां एक ही वस्तु के संदर्भों की एक जोड़ी समान-लेकिन-अलग-अलग वस्तुओं के संदर्भों की एक जोड़ी के बराबर शब्दार्थ हो सकती है, लेकिन फिर भी कुछ फायदे हैं। उदाहरण के लिए, एक ही पचास-हज़ार-वर्ण स्ट्रिंग के दो संदर्भों की समानता के लिए जाँच की जा सकती है ...
सुपरकैट

2
... उस लंबाई के दो अलग-अलग-लेकिन-समान तारों के संदर्भ से बहुत तेज।
सुपरकाट

5

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

किसी भी स्थिति में, आपको इन चीजों के बारे में तब तक चिंता करना शुरू नहीं करना चाहिए जब तक कि आपने अनुमान लगाने के बजाय वास्तविक प्रदर्शन की अड़चनों को निर्धारित करने के लिए अपना कोड निर्धारित नहीं कर लिया हो। तब तक, आपको कोड पठनीयता के लिए सबसे अच्छा होना चाहिए, प्रदर्शन नहीं।


जावा के शुरुआती संस्करणों में कचरा कलेक्टर द्वारा छोड़ी गई वस्तुओं को साफ करने पर काफी लागत आती थी। जावा के हाल के संस्करणों ने जीसी विकल्पों को बहुत बढ़ाया है, इसलिए ऑब्जेक्ट निर्माण शायद ही कभी एक मुद्दा है। आमतौर पर वेब सिस्टम IO कॉल द्वारा बाहरी सिस्टम तक सीमित होते हैं जब तक कि आप पेज लोड के भाग के रूप में एप्लिकेशन सर्वर पर वास्तव में कुछ जटिल नहीं कर रहे हैं।
ग्रेग

3

मुझे लगता है कि आपके सहयोगी ने अनावश्यक वस्तु निर्माण के दृष्टिकोण से कहा होगा। मेरा मतलब है कि यदि आप एक ही वस्तु बार-बार बना रहे हैं तो उस वस्तु को साझा करना बेहतर है। यहां तक ​​कि ऐसे मामलों में जहां ऑब्जेक्ट निर्माण जटिल है और अधिक मेमोरी लेता है, आप उस ऑब्जेक्ट को क्लोन करना चाहते हैं और उस जटिल ऑब्जेक्ट निर्माण प्रक्रिया को बनाने से बच सकते हैं (लेकिन यह आपकी आवश्यकता पर निर्भर करता है)। मुझे लगता है कि "वस्तु निर्माण महंगा है" कथन को संदर्भ में लिया जाना चाहिए।

जहाँ तक जेवीएम मेमोरी आवश्यकताओं का सवाल है, जावा 8 की प्रतीक्षा करें, आपको -Xmx को निर्दिष्ट करने की भी आवश्यकता नहीं है, मेटा स्पेस सेटिंग्स जेवीएम मेमोरी की आवश्यकता का ध्यान रखेगी और यह अपने आप बढ़ेगी।


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

1
स्टैक एक्सचेंज में उपयोगकर्ताओं को सूचित करने के लिए कुछ तंत्र होना चाहिए जो किसी भी उत्तर को वोट करते हैं, जब उस उत्तर पर टिप्पणी पोस्ट की जाती है।
एकेएस

1

स्मृति को आवंटित करने की तुलना में एक वर्ग बनाने के लिए अधिक है। वहाँ भी आरंभीकरण है, मुझे यकीन नहीं है कि वह हिस्सा सभी उत्तरों द्वारा कवर नहीं किया गया है। सामान्य कक्षाओं में कुछ चर होते हैं, और कुछ प्रकार के आरंभीकरण होते हैं, और यह मुफ़्त नहीं है। कक्षा क्या है, इसके आधार पर, यह फ़ाइलों को पढ़ सकता है, या किसी अन्य धीमी गति से संचालन कर सकता है।

तो बस विचार करें कि वर्ग निर्माता क्या करता है, यह पता लगाने से पहले कि यह मुफ़्त है या नहीं।


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

2
अगर अतिरिक्त लागत को 'अगर (पहली बार)' में ले जाया जाता है, तो एक लूप में क्लास को फिर से बनाना क्लास को री यूज़ करने से ज्यादा महंगा होता है।
एलेक्स

मैं एक समान उत्तर पोस्ट करने वाला था, और मुझे विश्वास है कि यह सही उत्तर है। इतने सारे लोग उन बातों से अंधे हो जाते हैं कि जावा ऑब्जेक्ट्स बनाना सस्ता है, उन्हें इस बात का एहसास नहीं है कि अक्सर कंस्ट्रक्टर या आगे की शुरूआत सस्ते से बहुत दूर हो सकती है। उदाहरण के लिए, स्विंग में ImageIcon वर्ग, भले ही आप इसे एक प्री-लोडेड इमेज ऑब्जेक्ट से गुजारें, कंस्ट्रक्टर काफी महंगा है। और मैं @GordonM से असहमत हूं, JDK के कई वर्ग कंस्ट्रक्टर में अधिकांश init का प्रदर्शन करते हैं, और मुझे लगता है कि यह कोड को दुबला बनाता है, बेहतर डिज़ाइन किया गया है।
qwertzguy

1

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

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

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

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

मुझे एक सहकर्मी ने बताया था कि जावा ऑब्जेक्ट निर्माण सबसे महंगा ऑपरेशन है जिसे आप कर सकते हैं। इसलिए मैं केवल कुछ वस्तुओं को यथासंभव बनाने के लिए निष्कर्ष निकाल सकता हूं।

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


1
आपका पहला पैराग्राफ सही रास्ते पर है। एडेन और युवा रिक्त स्थान कॉपी कलेक्टर का उपयोग करते हैं जिनके पास लगभग है। मृत वस्तुओं के लिए 0 लागत। मैं इस प्रस्तुति की अत्यधिक अनुशंसा करता हूं । एक साइड नोट पर, आपको पता है कि यह सवाल 2012 से है, है ना?
जिमीजैम

@JimmyJames मैं ऊब गया हूं और पुराने प्रश्नों सहित सिर्फ सवालों के माध्यम से झारना चाहता हूं। मुझे आशा है कि लोगों को मेरी नेक्रोमेंसी से ऐतराज नहीं होगा! :-D
ड्रैगन एनर्जी

@ जिमीजैम क्या अब ऐसा नहीं है कि बॉक्सिंग प्रकारों में अतिरिक्त मेमोरी आवश्यकताएं हैं और किसी सरणी में सन्निहित होने की गारंटी नहीं है? मुझे लगता है कि जावा में वस्तुएं सस्ती हैं, लेकिन एक मामला जहां वे अपेक्षाकृत महंगे हो सकते हैं, float[]बनाम की तरह है Float[], जहां पूर्व के क्रमिक रूप से एक मिलियन का प्रसंस्करण करना दूसरे की तुलना में काफी तेज हो सकता है।
ड्रैगन एनर्जी

1
जब मैंने पहली बार यहां पोस्टिंग शुरू की तो मैंने भी ऐसा ही किया। जब पुराने प्रश्नों के उत्तर बहुत कम मिलते हैं तो आप आश्चर्यचकित न हों।
जिमीजैम

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

0

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

यह कहा कि यह अभी भी एक लागत है, और कभी-कभी आप अपने आप को संभव के रूप में कई वस्तु को स्क्रैप करने की कोशिश कर सकते हैं। लेकिन प्रोफाइलिंग के बाद ही पता चला है कि यह एक समस्या है।

यहाँ इस विषय पर एक शानदार प्रस्तुति दी गई है: https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf


0

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


ऐसा लगता है कि पहले से बनाए गए 15 से अधिक उत्तरों में कुछ भी महत्वपूर्ण नहीं है। शायद ही कोई ऐसा प्रश्न पूछे जाने के लायक हो, जो 2 साल पहले पूछा गया हो और बहुत ही गहन उत्तर दिया हो
gnat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.