java - जावा में थ्रेड के थ्रॉटलिंग सीपीयू/मेमोरी उपयोग?




memory multithreading (6)

मैं एक ऐसा एप्लीकेशन लिख रहा हूं जिसमें एकाधिक थ्रेड चलेंगे, और उन धागे के सीपीयू / मेमोरी उपयोग को थ्रॉटल करना चाहते हैं।

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

संपादित करें: एक बक्षीस जोड़ा गया; मैं इस पर कुछ वाकई अच्छे, अच्छी तरह से विचारों को सोचना चाहता हूं।

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

जिस तरह से लिखा गया है, यह निष्पादित होने वाली प्रत्येक कक्षा के लिए अलग-अलग प्रक्रियाओं को बनाने के लिए रिफैक्टर का दर्द होगा। यदि वीएम तर्कों के माध्यम से स्मृति उपयोग को सीमित करने का यही एकमात्र अच्छा तरीका है, तो हो सकता है। लेकिन मैं जानना चाहता हूं कि धागे के साथ ऐसा करने का कोई तरीका है या नहीं। एक अलग प्रक्रिया के रूप में, मैं अपने CPU उपयोग को किसी भी तरह सीमित करने में सक्षम होना चाहता हूं, जैसा कि मैंने पहले उल्लेख किया था, इनमें से कई एक बार में निष्पादित होंगे। मैं एक अनंत लूप नहीं चाहता हूं कि सभी संसाधनों को गले लगाएं।

संपादित करें 3: ऑब्जेक्ट आकार का अनुमान लगाने का एक आसान तरीका जावा के Instrumentation कक्षाओं के साथ है; विशेष रूप से, GetObjectSize विधि। ध्यान दें कि इस उपकरण का उपयोग करने के लिए कुछ विशेष सेटअप की आवश्यकता है।


"थ्रेडिंग" करने के बजाय सहकारी मल्टीटास्किंग करने के बजाय, यह देखना दिलचस्प होगा कि क्या आप http://www.janino.net/ को एक निश्चित समय / इंस्ट्रक्शन के सेट के लिए प्रोग्राम चलाने के लिए उपयोग कर सकते हैं, फिर रुकें और चलाएं अगला कार्यक्रम कम से कम इस तरह के मेले, हर किसी को एक ही समय टुकड़ा दें ...


Thread.setPriority () मदद कर सकता है, लेकिन यह आपको थ्रेड द्वारा उपयोग किए गए CPU को कैप करने की अनुमति नहीं देता है। असल में, मैंने किसी भी जावा लाइब्रेरी के बारे में नहीं सुना है जो ऐसा करता है।

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

लागू करने के लिए एक और सैद्धांतिक मार्ग Isolates का उपयोग करना होगा। दुर्भाग्य से, सामान्य उद्देश्य JVM को खोजने के लिए आपको कठोर दबाव डाला जाएगा जो लागू करता है। इसके अलावा, मानक एपीआई केवल आपको अलगाव के नियंत्रण में, अलग-अलग धागे को नियंत्रित करने की अनुमति नहीं देती है।


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

कुछ डिग्री के लिए CPU उपयोग को नियंत्रित करने के लिए, आप Thread.setPriority() उपयोग कर सकते हैं।

स्मृति के लिए, प्रति थ्रेड मेमोरी जैसी कोई चीज नहीं है। जावा थ्रेड्स की अवधारणा का मतलब साझा स्मृति है। स्मृति उपयोग को नियंत्रित करने का एकमात्र तरीका कमांड लाइन विकल्पों जैसे -Xmx के माध्यम से है, लेकिन रनटाइम पर सेटिंग्स में हेरफेर करने का कोई तरीका नहीं है।


आप धागे को विभिन्न प्राथमिकताओं को असाइन कर सकते हैं ताकि सबसे प्रासंगिक धागा अधिक बार निर्धारित हो।

यह answer देखने के लिए देखें कि क्या यह मदद करता है।

जब सभी चलने वाले धागे की समान प्राथमिकता होती है तो वे इस तरह चल सकते हैं:

t1, t2, t3,     t1, t2, t3,   t1, t2, t3

जब आप उनमें से किसी को एक अलग प्राथमिकता देते हैं तो यह ऐसा दिखाई दे सकता है:

t1, t1, t1, t1,    t2,    t1, t1, t1 t3.

यही है, पहला धागा बाकी "अक्सर" चलाता है।


यदि आप धागे को एक अलग प्रक्रिया में चलाते हैं तो आप स्मृति उपयोग को कैप कर सकते हैं और CPU की संख्या को सीमित कर सकते हैं या इन धागे की प्राथमिकता को बदल सकते हैं।

हालांकि, आप जो भी करते हैं, वह ओवरहेड और जटिलता को जोड़ने की संभावना है जो अक्सर काउंटर-उत्पादक होता है।

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

मेमोरी उपयोग को प्रतिबंधित करना आसान नहीं है क्योंकि साझा किया गया केवल एक ही ढेर है। तो एक वस्तु जो एक धागे में प्रयोग की जाती है वह दूसरे में प्रयोग योग्य है और इसे एक थ्रेड या किसी अन्य को असाइन नहीं किया जाता है।

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


सीपीयू को कम करने के लिए, यदि आप लूप्स के दौरान और अपने थ्रेड को आम के अंदर सोना चाहते हैं।

while(whatever) {
    //do something
    //Note the capitol 'T' here, this sleeps the current thread.
    Thread.sleep(someNumberOfMilliSeconds);
}

कुछ सौ मिलीसेकंड के लिए सोते हुए प्रदर्शन पर बहुत कम ध्यान देने योग्य परिणाम के साथ CPU उपयोग को बहुत कम कर देगा।

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





throttling