2008-12-12 7 views
6

एक कार्यक्रम में तंग लूपिंग खराब है?क्या कसकर लूपिंग खराब है?

मेरे पास एक ऐसा एप्लिकेशन है जिसमें गेम-भौतिकी सिम्युलेटर के लिए दो धागे हैं। एक अद्यतनगाम धागा और एक रेंडर धागा। रेंडर थ्रेड को कुछ मिलीसेकंड (फ्रेम फ्रेम को प्राप्त करने के लिए) के लिए थ्रेड सोने के कारण थ्रॉटल किया जाता है और अपडेटगैम थ्रेड (जो कुछ भौतिकी समीकरणों के आधार पर गेम ऑब्जेक्ट्स पोजीशन में अपडेट करता है) पहले 10 मिलीसेकंद नींद से थका हुआ था ।

हालांकि, मैंने हाल ही में अपडेटगैम थ्रेड को अनदेखा कर दिया है और मेरे ऑब्जेक्ट्स आंदोलन का सिमुलेशन अब और अधिक यथार्थवादी प्रतीत होता है कि मैंने 10ms नींद ली है। क्या यह गर्म लूप के लिए बुरा है या एक तंग लूप है?

private class UpdateTask implements Runnable 
{ 
    private long previousTime = System.currentTimeMillis(); 
    private long currentTime = previousTime; 
    private long elapsedTime; 


    public void run() 
    { 
     while(true) 
     { 
     currentTime = System.currentTimeMillis(); 
     elapsedTime = (currentTime - previousTime); // elapsed time in seconds 


     updateGame(elapsedTime/1000f); 

      try { 
       Thread.currentThread().sleep(1); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     previousTime = currentTime; 
     } 
    } 
} 

इस उदाहरण मैं सिर्फ 1ms के लिए सो रहा हूँ (और मेरी समझ से कैसे मिलीसेकंड सटीकता और नींद समारोह काम करता है यह शायद अधिक 5-10ms की तरह है के साथ। अगर मैं इस से किसी भी अधिक के लिए सोने के प्रारंभ होने पर मेरी टक्कर पता लगाने और भौतिकी मॉडल की सटीकता पर प्रभाव डालता है करने के लिए।

यह एक बुरा व्यवहार तंग छोरों या उन में 1ms सोता साथ लूप के लिए है? वहाँ कुछ और मैं इसके बजाय क्या करना चाहिए है?

+1

आप का उपयोग करना चाहिए '' 'Thread.currentThread()। नींद के बजाय Thread.Sleep (...) (पर कैसे और क्यों आप धागे का उपयोग कर रहे और लॉकिंग आदि देखने के लिए है। ..) 'क्योंकि यह एक स्थिर विधि है; आपका कोड आपको 'someOtherThread.sleep (...)' करने के लिए प्रेरित कर सकता है जो 'कुछ अन्य थ्रेड' नहीं सोता है। – newacct

उत्तर

9

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

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

+0

मेरे पास दो धागे हैं, मेरा अपडेट गेम थ्रेड और मेरा प्रतिपादन धागा है। मेरा प्रतिपादन थ्रेड अधिकतमफ्रेमरेट पर बंद कर दिया गया है जैसा कि आप कहते हैं कि यह समाप्त हो गया है। – mmcdole

+0

@joshperry, अब लेख पढ़ना – mmcdole

+0

'अपना टाइमस्टेप ठीक करें' के लिए बड़ा अपवॉट। अंधेरे युग में वापस हमने पाठ को न्यायसंगत बनाने के लिए समान तकनीकों का उपयोग किया! –

2

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

2

जैसा कि एडम ने अपने उत्तर में बताया है, सिस्टम के प्रदर्शन पर प्रतिकूल प्रभाव हो सकता है।

मैंने गेम को बहुत ही समान तरीके से बनाने की कोशिश की है (अलग-अलग धागे पर प्रतिपादन और गति गणनाएं) और मुझे पता चला है कि Thread.sleep नहीं होने से जावा एप्लिकेशन CPU का एक बहुत महत्वपूर्ण हिस्सा लेगा पहर।

विचार करने की एक और बात यह है कि सिस्टम टाइमर स्वयं ही है। जैसा कि आपने उल्लेख किया है, यद्यपि Thread.sleep विधि मिलीसेकंड की संख्या में सोती है, लेकिन ऑपरेटिंग सिस्टम द्वारा प्रदान किए गए टाइमर पर यह सटीकता निर्भर है (जैसा कि एपीआई विनिर्देशों में उल्लेख किया गया है)। विंडोज एनटी-आधारित ऑपरेटिंग सिस्टम के मामले में, timer resolution is 10 milliseconds। (यह भी देखें: System.currentTimeMillis vs System.nanoTime)

हां, यह सच है कि Thread.sleep होने से आपके आवेदन के प्रदर्शन को कम करने की क्षमता है, लेकिन ऐसा नहीं होने से एप्लिकेशन द्वारा सिस्टम का उपयोग आसमान में बढ़ने का कारण बन सकता है।

मुझे लगता है कि यह निर्णय नीचे आता है कि एप्लिकेशन को सिस्टम उपयोग का एक महत्वपूर्ण हिस्सा लेना चाहिए या सिस्टम पर चल रहे अन्य अनुप्रयोगों के साथ सीपीयू समय को अच्छा प्रदर्शन करना चाहिए। Fix Your Timestep!

जब एक खेल चल रहा है कि आम तौर पर मुख्य अनुप्रयोग है कि उपयोगकर्ता के बारे में इतना तंग पाशन परवाह करता है कि एक समझौते के बड़ा नहीं है:

0

एक खेल के लिए, शायद नहीं। बस यह सुनिश्चित करें कि स्विचेस कार्य करते समय आपका गेम रुक जाता है।

0

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

1

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

1

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

यदि कोई कार्य cmd के लिए मल्टी-थ्रेड/कोर के हैंडलर का उपयोग करना चाहता है (यदि यह एक ईवेंट प्रकार मॉडल है - मुझे व्यक्तिगत रूप से ईवेंट मॉडल पसंद है - वैश्विक सिंगलेट की आवश्यकता के बिना साझा राज्य जानकारी तक पहुंच बनाना आसान है) फिर कई कार्यों को बढ़ा सकते हैं (मौजूदा थ्रेड पूल का उपयोग करके कहें - इसलिए नए धागे की लागत हर सीएमडी पर नहीं आती है) और फिर सभी कार्यों को पूरा करने के लिए बाधा प्रकार वर्ग का उपयोग करें। यह विधि आमतौर पर लॉकिंग को आसान बनाता है, क्योंकि प्रत्येक cmd (या सिस्टम) में आमतौर पर अलग-अलग लॉकिंग आवश्यकताएं होती हैं। इस प्रकार आप केवल उस सिस्टम के लिए लॉकिंग को कार्यान्वित कर सकते हैं और उप सिस्टम के बीच लॉकिंग के बारे में चिंता करने की ज़रूरत नहीं है - यानी। भौतिकी के लिए आप खेल क्षेत्र में वस्तुओं के बंडलों को लॉक कर सकते हैं, और थ्रेड पूल में प्रत्येक फोर्कड थ्रेड को तो इसके ऑब्जेक्ट्स के बारे में चिंता करते हैं यानी। थ्रेड 1 ऑब्जेक्ट्स 1 से 20, थ्रेड 2 ऑब्जेक्ट्स 21-40 इत्यादि को संभालने के लिए है (यह सिर्फ यह समझने के लिए है कि प्रत्येक सीएमडी कस्टम लॉकिंग एल्गोरिदम को कैसे कार्यान्वित कर सकती है जो कि यह क्या कर रही है, इसके बारे में चिंता करने के बिना, अन्य सब सिस्टम क्या कर रहे हैं साझा राज्य डेटा के साथ)।

महत्वपूर्ण बात यह है

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