[erlang-questions] I'm having a SNAFU moment: timer:sleep/1

Jesper Louis Andersen <>
Mon Jan 12 12:43:06 CET 2015


Hi Roberto,

I'm not sure what you would expect here. timer:sleep/1 has an
implementation like this:

sleep(T) ->
    receive
    after T -> ok
    end.

which is what other people told you also. In general, such timing
constructs have no guarantee about when they will fire, only that they will
fire after the time has elapsed. So what you are seeing is somewhat
expected behaviour. The more fine-grained and the more timers you have, the
less precise things will get. In a way, this is one of the properties which
makes Erlang a soft-realtime system and not a hard-realtime one, although
the precise definition of soft/hard realtime are subtly different.

I believe there were some effort being made by the OTP team to address lock
contention around the timer wheel, so the code might change behaviour by
quite a lot in the future. It might even have to get worse for
single-process timers in order to become better for multi-process timers.


On Mon Jan 12 2015 at 12:20:15 PM Roberto Ostinelli <>
wrote:

> Indeed. From very basic try-outs:
>
> 1>  test:sleep_periodical(6, 1000).
> Finished in 6022381 microseconds.
> ok
> 2>  test:sleep_periodical(12, 500).
> Finished in 6042683 microseconds.
> ok
> 3>  test:sleep_periodical(24, 250).
> Finished in 6062096 microseconds.
> ok
> 4>  test:sleep_periodical(48, 125).
> Finished in 6133169 microseconds.
> ok
> 5> test:sleep_periodical(96, 62).
> Finished in 6320419 microseconds.
> ok
> 6> test:sleep_periodical(192, 31).
> Finished in 6492321 microseconds.
> ok
> 7> test:sleep_periodical(384, 16).
> Finished in 7327693 microseconds.
> ok
>
> So it somewhat is ok until we get in the 125ms range.
>
>
>
> On Mon, Jan 12, 2015 at 12:12 PM, Sergej Jurečko <
> > wrote:
>
>> timer:sleep is not even remotely as accurate for those low numbers. It
>> can not go lower than 20ms or so from what i remember.
>>
>> I have had this issue once when I needed low interval for timer. I used
>> an external c app which printed to stdout every 5ms. I dont think there is
>> any way in erlang to get a timer that low.
>>
>> Sergej
>> On Jan 12, 2015 11:46 AM, "Roberto Ostinelli" <>
>> wrote:
>>
>>> Additionally:
>>>
>>> 6> test:sleep_periodical(1000, 1).
>>> Finished in 1999097 microsecond
>>>
>>> So:
>>>
>>>    - Looping 1,000 times and sleeping 1 ms each time takes 2.00 seconds
>>>    (instead of 1).
>>>
>>> Looks like it's ms related, not total count.
>>>
>>> Best,
>>> r.
>>>
>>>
>>>
>>> On Mon, Jan 12, 2015 at 11:40 AM, Roberto Ostinelli <
>>> > wrote:
>>>
>>>> Dear list,
>>>> I've probably missed out something since I'm not understanding what is
>>>> going here.
>>>>
>>>> I'm basically just trying to send messages periodically, though I found
>>>> out that I wasn't seeing the behavior that I was expecting. It looks like
>>>> the timer has some erratic behavior.
>>>>
>>>> I've stripped out the code to the bare minimum and it looks like this:
>>>>
>>>> -module(test).
>>>> -export([sleep_periodical/2]).
>>>> -export([sleep_loop/2]).
>>>>
>>>> sleep_periodical(Num, IntervalMs) ->
>>>> {Time, _Value} = timer:tc(?MODULE, sleep_loop, [Num, IntervalMs]),
>>>> io:format("Finished in ~p microseconds.~n", [Time]).
>>>>
>>>> sleep_loop(Num, IntervalMs) ->
>>>> SleepFun = fun(_) -> timer:sleep(IntervalMs) end,
>>>> lists:foreach(SleepFun, lists:seq(1, Num)).
>>>>
>>>>
>>>> When I run this code, I see the following:
>>>>
>>>> Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:8:8] [async-threads:10]
>>>> [hipe] [kernel-poll:false] [dtrace]
>>>>
>>>> Eshell V6.3  (abort with ^G)
>>>> 1> c(test).
>>>> {ok,test}
>>>> 2> test:sleep_periodical(1000, 10).
>>>> Finished in 12257397 microseconds.
>>>> ok
>>>> 3> test:sleep_periodical(2000, 10).
>>>> Finished in 24518070 microseconds.
>>>> ok
>>>> 4> test:sleep_periodical(10000, 1).
>>>> Finished in 20000280 microseconds.
>>>> ok
>>>> 5> test:sleep_periodical(20000, 1).
>>>> Finished in 40000685 microseconds.
>>>> ok
>>>>
>>>> So:
>>>>
>>>>    - Looping 1,000 times and sleeping 10 ms each time takes 12.26
>>>>    seconds (instead of 10).
>>>>    - Looping 2,000 times and sleeping 10 ms each time takes 24.52
>>>>    seconds (instead of 20).
>>>>    - Looping 10,000 times and sleeping 1 ms each time takes 20.00
>>>>    seconds (instead of 10).
>>>>    - Looping 20,000 times and sleeping 1 ms each time takes 40.00
>>>>    seconds (instead of 20).
>>>>
>>>> Up to 10,000 times it takes 12,16% (1/8) more time, from 10,000 times
>>>> it takes 100% (double).
>>>>
>>>> Can some kind soul explain what I'm doing wrong here and how to achieve
>>>> the desired results?
>>>>
>>>> I'm on OSX, Erlang 17.4.
>>>>
>>>> Help! ^^_
>>>> r.
>>>>
>>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> 
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150112/740a9bb9/attachment.html>


More information about the erlang-questions mailing list