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

Roberto Ostinelli roberto@REDACTED
Mon Jan 12 17:03:54 CET 2015


Hi Jesper,
I was expecting a more precise timer, that is all. :)
Thank you for your input.

So: how can someone execute an action every 1ms?

Best,
r.

On Mon, Jan 12, 2015 at 12:43 PM, Jesper Louis Andersen <
jesper.louis.andersen@REDACTED> wrote:

> 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 <roberto@REDACTED>
> 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 <
>> sergej.jurecko@REDACTED> 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" <roberto@REDACTED>
>>> 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 <
>>>> roberto@REDACTED> 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
>>>> erlang-questions@REDACTED
>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>>
>>>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150112/fe53a1f7/attachment.htm>


More information about the erlang-questions mailing list