2016-07-07 10 views
10

मेरे समस्या:प्रतीक्षा कर रहा है धागे संसाधन उपभोग

JVM में धागे की बड़ी संख्या संसाधन (स्मृति, CPU), जब धागे TIMED_WAIT राज्य कर रहे हैं का उपयोग करते है (सो नहीं)> समय की 99.9% ? जब धागे इंतजार कर रहे हैं, तो किसी भी चीज की आवश्यकता होने पर उन्हें बनाए रखने के लिए कितना सीपीयू ओवरहेड खर्च होता है?

क्या उत्तर गैर-जेवीएम से संबंधित वातावरण (जैसे लिनक्स कर्नल) पर भी लागू होता है?

प्रसंग:

मेरे कार्यक्रम अंतरिक्ष उपभोक्ता संकुल की एक बड़ी संख्या प्राप्त करता है। यह विभिन्न पैकेजों के भीतर समान गुणों की गणना करता है। पैकेज प्राप्त करने के बाद दिए गए समय के बाद (घंटे या दिन हो सकते हैं), वह विशिष्ट पैकेज समाप्त हो जाता है और पैकेज में योगदान किए गए किसी भी गिनती को कम किया जाना चाहिए।

वर्तमान में, मैं स्मृति या डिस्क में सभी संकुलों को संग्रहीत करके इन कार्यक्षमताओं को प्राप्त करता हूं। हर 5 मिनट में, मैं भंडारण से समाप्त हो चुके पैकेज हटा देता हूं, और गुणों की गणना करने के लिए शेष संकुलों को स्कैन करता हूं। यह विधि बहुत मेमोरी का उपयोग करती है, और इसमें समय और स्मृति के लिए खराब समय जटिलता (O(n) है जहां n अप्रत्याशित संकुलों की संख्या है)। यह कार्यक्रम की भयानकता को भयानक बनाता है।

इस समस्या से संपर्क करने का एक वैकल्पिक तरीका पैकेज द्वारा हर बार विशेषता गणना में वृद्धि करना है और Timer() थ्रेड शुरू करना है जो पैकेज की समाप्ति के बाद विशेषता गणना को कम करता है। यह सभी भारी पैकेजों को स्टोर करने और समय जटिलता को O(1) में बदलने की आवश्यकता को समाप्त करता है। हालांकि, यह एक और समस्या पैदा करता है क्योंकि मेरा प्रोग्राम O(n) धागे की संख्या शुरू कर देगा, जो प्रदर्शन में कटौती कर सकता है। चूंकि अधिकांश धागे TIMED_WAIT राज्य में होंगे (जावा का Timer()Object.wait(long) विधि को आमंत्रित करता है) उनके जीवन चक्र का विशाल बहुमत, क्या यह अभी भी सीपीयू को बहुत बड़े तरीके से प्रभावित करता है?

+0

आप कितने धागे सोच रहे हैं इंतजार कर रहे हैं? धागे की जांच करने के लिए कर्नेल पर कुछ सौ या उससे अधिक नहीं हो सकता है और जब उन्हें निर्धारित करने की आवश्यकता होती है, लेकिन यदि आप 500+ कतारबद्ध कर रहे हैं, तो आप अपने दृष्टिकोण पर फिर से विचार करना चाहेंगे .. – txtechhelp

+0

मैं शायद दो सौ से अधिक है। क्या आप कृपया बता सकते हैं कि कर्नेल को लगातार 'TIMED_WAIT' पर धागे की जांच क्यों करनी है? मैंने यह जानकारी खोजने की कोशिश की कि कर्नेल यह कैसे विशेष रूप से करता है लेकिन किसी भी वांछनीय जानकारी को नहीं ढूंढ सकता है। – PhotometricStereo

+1

अनुसूचित एक्सप्लोरर/एक थ्रेड के साथ समाप्ति के टाइमस्टैम्प द्वारा प्राथमिकता कतार। – zapl

उत्तर

9

पहला, जावा (या .NET) थ्रेड! = एक कर्नेल/ओएस थ्रेड।

एक जावा Thread एक उच्च स्तरीय रैपर है जो सिस्टम थ्रेड की कुछ कार्यक्षमताओं को सारणीबद्ध करता है; इन प्रकार के धागे को प्रबंधित धागे के रूप में भी जाना जाता है। कर्नेल स्तर पर एक थ्रेड में केवल 2 राज्य होते हैं, दौड़ते हैं और नहीं चलते हैं। कुछ प्रबंधन जानकारी (स्टैक, निर्देश पॉइंटर्स, थ्रेड आईडी इत्यादि) है कि कर्नेल ट्रैक रखता है, लेकिन कर्नेल स्तर पर TIMED_WAITING स्थिति में मौजूद थ्रेड के रूप में ऐसी कोई चीज़ नहीं है (WaitSleepJoin के बराबर .NET राज्य)। वे "राज्य" केवल उन प्रकार के संदर्भों में मौजूद हैं (सी ++ std::thread में state सदस्य क्यों नहीं है) का हिस्सा है।

यह कहकर कि, जब एक प्रबंधित धागा अवरुद्ध किया जा रहा है, तो इसे दो तरीकों से किया जा रहा है (इस पर निर्भर करता है कि प्रबंधित स्तर पर अवरुद्ध होने का अनुरोध कैसे किया जा रहा है); थ्रेडिंग कोड के लिए ओपनजेडीके में मैंने जो कार्यान्वयन देखा है, वह प्रबंधित प्रतीक्षाों को संभालने के लिए सेमफोर का उपयोग करता है (जो मैंने अन्य सी ++ फ्रेमवर्क में देखा है जिसमें एक प्रकार का "प्रबंधित" थ्रेड क्लास के साथ-साथ .NET कोर में भी है पुस्तकालय), और अन्य प्रकार के इंतजार/ताले के लिए एक म्यूटेक्स का उपयोग करें।

चूंकि अधिकांश कार्यान्वयन कुछ प्रकार के लॉकिंग तंत्र (जैसे सेमाफोर या म्यूटेक्स) का उपयोग करेंगे, कर्नेल आम तौर पर वही काम करता है (कम से कम जहां आपका प्रश्न चिंतित है); यानी, कर्नेल "रन" कतार के धागे को बंद कर देगा और इसे "प्रतीक्षा" कतार में रखेगा (context switch)।थ्रेड शेड्यूलिंग में प्राप्त करना और विशेष रूप से कर्नेल थ्रेड के निष्पादन को कैसे नियंत्रित करता है, इस क्यू & ए के दायरे से बाहर है, खासकर जब से आप जावा और जावा के संबंध में हैं, तो कुछ अलग-अलग प्रकार के ओएस पर चल सकते हैं (जिनमें से प्रत्येक थ्रेडिंग को पूरी तरह से अलग करता है)। JVM में धागे की बड़ी संख्या का उपभोग संसाधन (स्मृति, CPU), जब धागे हैं TIMED_WAIT राज्य (नहीं सो)> 99.9 समय की% का एक बहुत

है:

आपके प्रश्नों का उत्तर देना अधिक सीधे ?

इस के लिए

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

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

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

जब धागे इंतजार कर रहे हैं, तो किसी भी चीज की आवश्यकता होने पर उन्हें बनाए रखने के लिए कितना सीपीयू ओवरहेड खर्च होता है?

कोई नहीं। ऊपर देखें, लेकिन धागे का प्रबंधन करने के लिए प्रयुक्त CPU ओवरहेड थ्रेड संदर्भ के आधार पर नहीं बदलता है। अतिरिक्त सीपीयू का उपयोग संदर्भ स्विचिंग के लिए किया जा सकता है और सक्रिय रूप से अतिरिक्त CPU का उपयोग स्वयं सक्रिय होने पर धागे द्वारा किया जाएगा, लेकिन सीपीयू को को एक प्रतीक्षा थ्रेड बनाम चलने वाले धागे को बनाए रखने के लिए कोई अतिरिक्त "लागत" नहीं है।

क्या उत्तर गैर-जेवीएम से संबंधित वातावरण (जैसे लिनक्स कर्नल) पर भी लागू होता है?

हां और नहीं। जैसा कि कहा गया है, प्रबंधित संदर्भ आम तौर पर उन अधिकांश प्रकार के वातावरण (जैसे जावा, .NET, PHP, लुआ इत्यादि) पर लागू होते हैं, लेकिन उन संदर्भों में भिन्नता हो सकती है और थ्रेडिंग मुहावरे और सामान्य कार्यक्षमता कर्नेल का उपयोग करने पर निर्भर होती है। इसलिए जब एक विशिष्ट कर्नेल प्रति प्रक्रिया 1000+ धागे को संभालने में सक्षम हो सकता है, तो कुछ में कठोर सीमा हो सकती है, अन्य लोगों को प्रति प्रक्रिया उच्च थ्रेड गणना के साथ अन्य समस्याएं हो सकती हैं; आपको यह देखने के लिए ओएस/सीपीयू चश्मा का संदर्भ देना होगा कि आपके पास किस तरह की सीमाएं हो सकती हैं।

के बाद से धागे के सबसे TIMED_WAIT राज्य में हो जाएगा उनके जीवन चक्र के विशाल बहुमत, (जावा के टाइमर() Object.wait (लंबी) विधि invokes) यह अभी भी एक बहुत बड़ी रास्ते में सीपीयू प्रभावित करता है ?

नहीं (अवरुद्ध धागे के बिंदु का हिस्सा), लेकिन कुछ विचार करने के लिए: क्या होगा यदि (थ्रेड केस) उन थ्रेडों के सभी (या> 50%) को एक ही समय में चलाने की आवश्यकता है?यदि आपके पास केवल आपके पैकेज का प्रबंधन करने वाले कुछ धागे हैं, तो यह कोई समस्या नहीं हो सकती है, लेकिन कहें कि आपके पास 500+ है; 250 धागे सभी एक ही समय में जागने जा रहे हैं बड़े पैमाने पर सीपीयू विवाद का कारण बनेंगे।

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

उम्मीद है कि मदद करता है।

+0

अच्छी व्याख्या। – hakunami

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