How to run a Erlang Process periodically with Precise Time (i.e. 10ms)

前端 未结 2 1870
-上瘾入骨i
-上瘾入骨i 2021-01-05 13:07

I want to run a periodic erlang process every 10ms (based on wall clock time), the 10ms should be as accurate as possible; what should be the right way to implement it?

2条回答
  •  太阳男子
    2021-01-05 13:13

    If you want really reliable and accurate periodic process you should rely on actual wall clock time using erlang:monotonic_time/0,1. If you use method in Stratus3D's answer you will eventually fall behind.

    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(),
        {noreply, S}.
    

    You can test in the shell:

    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).
    

提交回复
热议问题