2016-12-29 17 views
5

के साथ समय-समय पर एर्लांग प्रक्रिया कैसे चलाएं मैं हर 10ms (दीवार घड़ी के समय के आधार पर) आवधिक एरलांग प्रक्रिया को चलाने के लिए चाहता हूं, 10ms जितना संभव हो उतना सटीक होना चाहिए; इसे लागू करने का सही तरीका क्या होना चाहिए?सटीक समय (यानी 10ms)

उत्तर

6

तुम सच में विश्वसनीय और सटीक समय-समय पर प्रक्रिया आप erlang:monotonic_time/0,1 का उपयोग कर वास्तविक दीवार घड़ी समय पर भरोसा करना चाहिए चाहते हैं। यदि आप Stratus3D के answer में विधि का उपयोग करते हैं तो आप अंततः पीछे आ जाएंगे।

start_link(Period) when Period > 0, is_integer(Period) -> 
    gen_server:start_link({local, ?SERVER}, ?MODULE, Period, []). 

... 

init(Period) -> 
    StartT = erlang:monotonic_time(millisecond), 
    self() ! tick, 
    {ok, {StartT, Period}}. 

... 

handle_info(tick, {StartT, Period} = S) -> 
    Next = Period - (erlang:monotonic_time(millisecond)-StartT) rem Period, 
    _Timer = erlang:send_after(Next, self(), tick), 
    do_task(), 
    {ok, S}. 

आप खोल में परीक्षण कर सकते हैं:

spawn(fun() -> 
    P = 1000, 
    StartT = erlang:monotonic_time(millisecond), 
    self() ! tick, 
    (fun F() -> 
     receive 
      tick -> 
      Next = P - (erlang:monotonic_time(millisecond)-StartT) rem P, 
      erlang:send_after(Next, self(), tick), 
      io:format("X~n", []), 
      F() 
     end 
     end)() 
    end). 
+0

इस विधि के साथ अच्छी बात यह है कि छोटे अपरिहार्य त्रुटियों समय में जमा नहीं है। – Pascal

0

तुम सच में संभव के रूप में सटीक होना करने के लिए चाहते हैं और आप सुनिश्चित करें कि आपके काम अंतराल आप चाहते हैं यह आप पर प्रदर्शन के बजाय एक प्रक्रिया हर 10ms को उत्पन्न करने में से एक लंबी प्रक्रिया चल हो सकता था की तुलना में कम समय लगेगा कर रहे हैं। Erlang हर 10 एमएमएस में एक नई प्रक्रिया पैदा कर सकता है, लेकिन जब तक कोई कारण नहीं है कि आप एक ही प्रक्रिया का पुन: उपयोग नहीं कर सकते हैं, यह आम तौर पर ओवरहेड के लायक नहीं है (भले ही यह बहुत छोटा हो)।

मैं एक OTP gen_server में कुछ इस तरह करना होगा: जब तक

periodic_task:start_link(). 

रूप gen_server चल रहा है (अगर यह दुर्घटनाओं इसलिए माता-पिता करेंगे:

-module(periodic_task). 

... module exports 

start_link() -> 
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). 

... Rest of API and other OTP callbacks 

init([]) -> 
    Timer = erlang:send_after(0, self(), check), 
    {ok, Timer}. 

handle_info(check, OldTimer) -> 
    erlang:cancel_timer(OldTimer), 
    Timer = erlang:send_after(10, self(), check), 
    do_task(), % A function that executes your task 
    {noreply, Timer}. 

तो इस तरह gen_server शुरू प्रक्रिया से जुड़े हुए हैं) फ़ंक्शन do_task/0 लगभग हर 10 मिलीसेकंड निष्पादित किया जाएगा। ध्यान दें कि यह बिल्कुल सटीक नहीं होगा। निष्पादन समय में एक बहाव होगा। वास्तविक अंतराल 10ms + समय होगा जब यह टाइमर संदेश प्राप्त करता है, पुराने टाइमर को रद्द करता है, और नया शुरू करता है।

यदि आप प्रत्येक 10ms में एक अलग प्रक्रिया शुरू करना चाहते हैं तो आपके पास do_task/0 एक प्रक्रिया उत्पन्न हो सकती है। ध्यान दें कि यह अतिरिक्त ओवरहेड जोड़ देगा, लेकिन जरूरी नहीं कि स्पॉन्स के बीच अंतराल कम सटीक हो।

मेरे उदाहरण इस जवाब से लिया गया है: What's the best way to do something periodically in Erlang?

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