<div dir="ltr"><div><span class="">At least put erlang:yield() at the end of the loop. But to me that is just a gigantic waste of CPU.<br><br></span></div><span class="">This little c program as an external port does the job very nicely and hardly uses any resources.<br>int main(int argc, char *argv[])<br>{</span><br><span class=""><span class="">    char c[1];<br>    c[0] = 'a';<br></span>    for (;;)<br>    {<br>        usleep(3000);<br>        <br>        if (write(1, c, 1) <= 0)<br>            break;<br>    }<br>    <br>      return 0;<br>}<br></span></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 12, 2015 at 2:10 PM, Darach Ennis <span dir="ltr"><<a href="mailto:darach@gmail.com" target="_blank">darach@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Roberto,<div><br></div><div>If you want to avoid clock slewing or you need a timely and periodic event source you</div><div>can achieve this somewhat as follows, although the right solution will of course depend</div><div>on multiple factors.</div><div><br></div><div><div>-define(INTERVAL, 1000). % One second</div><div><br></div><div>main(_) -></div><div>  loop(now_ms(),0).</div><div><br></div><div>trigger(Now,Delta,Count) -></div><div>  io:format("At: ~p drift:~p rate:~p/sec~n", [Now, Delta - ?INTERVAL, Count]).</div><div><br></div><div>loop(Epoch,Count) -> </div><div>  Now = now_ms(),</div><div>  Delta = Now - Epoch,</div><div>  case Delta >= ?INTERVAL of</div><div>      true -> </div><div>          trigger(Now,Delta,Count),</div><div>          loop(Epoch+?INTERVAL,0);</div><div>      false -></div><div>          loop(Epoch,Count+1)<br></div><div>  end.</div><div><br></div><div>now_ms() -></div><div>  {Mega,Secs,Micros} = os:timestamp(),</div><div>  (Mega*1000000 + Secs)*1000 + (Micros div 1000).</div></div><div><br></div><div>This loops at a rate of ~7 million loops/second on my laptop and fires without</div><div>slew or significant drift consistently calling the trigger/3 function every second. The rub is I</div><div>burn a little more core/process for the privilege than with mechanism that induce slew such</div><div>as with timer or erlang:send_after directly. C'est la vie. Accuracy and timeliness aren't free.</div><div><br></div><div>In a gen_server you could use a combination of erlang:send_after and a clock based on</div><div>os:timestamp and an epoch as above so that you end up with a clock that is 'accurate enough'</div><div>for most use cases, and cheap enough for whatever value you ascribe to such tradeoffs given</div><div>the specifics of your use case.</div><div><br></div><div>Your mileage may vary.</div><div><br></div><div>Cheers,</div><div><br></div><div>Darach.</div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 12, 2015 at 11:43 AM, Jesper Louis Andersen <span dir="ltr"><<a href="mailto:jesper.louis.andersen@gmail.com" target="_blank">jesper.louis.andersen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Roberto,<br><br>I'm not sure what you would expect here. timer:sleep/1 has an implementation like this:<div><br></div><div>sleep(T) -></div><span><div>    receive</div><div>    after T -> ok</div><div>    end.</div></span><div><br>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.</div><div><br></div><div>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.</div><div><div><div><br></div><br><div class="gmail_quote">On Mon Jan 12 2015 at 12:20:15 PM Roberto Ostinelli <<a href="mailto:roberto@widetag.com" target="_blank">roberto@widetag.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Indeed. From very basic try-outs:<div><br></div><div><div><font face="monospace, monospace">1>  test:sleep_periodical(6, 1000). </font></div><div><font face="monospace, monospace">Finished in 6022381 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">2>  test:sleep_periodical(12, 500).</font></div><div><font face="monospace, monospace">Finished in 6042683 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">3>  test:sleep_periodical(24, 250).</font></div><div><font face="monospace, monospace">Finished in 6062096 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">4>  test:sleep_periodical(48, 125).  </font></div><div><font face="monospace, monospace">Finished in 6133169 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">5> test:sleep_periodical(96, 62).    </font></div><div><font face="monospace, monospace">Finished in 6320419 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">6> test:sleep_periodical(192, 31).</font></div><div><font face="monospace, monospace">Finished in 6492321 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">7> test:sleep_periodical(384, 16).</font></div><div><font face="monospace, monospace">Finished in 7327693 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div></div><div><br></div><div>So it somewhat is ok until we get in the 125ms range.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 12, 2015 at 12:12 PM, Sergej Jurečko <span dir="ltr"><<a href="mailto:sergej.jurecko@gmail.com" target="_blank">sergej.jurecko@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">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.</p>
<p dir="ltr">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.<br></p>
<p dir="ltr">Sergej</p>
<div class="gmail_quote"><div><div>On Jan 12, 2015 11:46 AM, "Roberto Ostinelli" <<a href="mailto:roberto@widetag.com" target="_blank">roberto@widetag.com</a>> wrote:<br type="attribution"></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir="ltr">Additionally:<div><br></div><div><div><font face="monospace, monospace">6> test:sleep_periodical(1000, 1). </font></div><div><font face="monospace, monospace">Finished in 1999097 microsecond</font></div></div><div><br></div><div>So:</div><div><ul><li>Looping 1,000 times and sleeping 1 ms each time takes 2.00 seconds (instead of 1).</li></ul><div>Looks like it's ms related, not total count.</div></div><div><br></div><div>Best,</div><div>r.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 12, 2015 at 11:40 AM, Roberto Ostinelli <span dir="ltr"><<a href="mailto:roberto@widetag.com" target="_blank">roberto@widetag.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Dear list,<div>I've probably missed out something since I'm not understanding what is going here.</div><div><br></div><div>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 <font face="monospace, monospace">timer</font> has some erratic behavior.</div><div><br></div><div>I've stripped out the code to the bare minimum and it looks like this:</div><div><br></div><div><div><font face="monospace, monospace">-module(test).</font></div><div><font face="monospace, monospace">-export([sleep_periodical/2]).</font></div><div><font face="monospace, monospace">-export([sleep_loop/2]).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sleep_periodical(Num, IntervalMs) -></font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap">        </span>{Time, _Value} = timer:tc(?MODULE, sleep_loop, [Num, IntervalMs]),</font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap">        </span>io:format("Finished in ~p microseconds.~n", [Time]).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sleep_loop(Num, IntervalMs) -></font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap">     </span>SleepFun = fun(_) -> timer:sleep(IntervalMs) end,</font></div><div><font face="monospace, monospace"><span style="white-space:pre-wrap">      </span>lists:foreach(SleepFun, lists:seq(1, Num)).</font></div></div><div><br></div><div><br></div><div>When I run this code, I see the following:</div><div><br></div><div><div><font face="monospace, monospace">Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Eshell V6.3  (abort with ^G)</font></div><div><font face="monospace, monospace">1> c(test).</font></div><div><font face="monospace, monospace">{ok,test}</font></div><div><font face="monospace, monospace">2> test:sleep_periodical(1000, 10).</font></div><div><font face="monospace, monospace">Finished in 12257397 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">3> test:sleep_periodical(2000, 10).</font></div><div><font face="monospace, monospace">Finished in 24518070 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">4> test:sleep_periodical(10000, 1).  </font></div><div><font face="monospace, monospace">Finished in 20000280 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div><div><font face="monospace, monospace">5> test:sleep_periodical(20000, 1).</font></div><div><font face="monospace, monospace">Finished in 40000685 microseconds.</font></div><div><font face="monospace, monospace">ok</font></div></div><div><br></div><div>So:</div><div><ul><li>Looping 1,000 times and sleeping 10 ms each time takes 12.26 seconds (instead of 10).</li><li>Looping 2,000 times and sleeping 10 ms each time takes 24.52 seconds (instead of 20).</li><li>Looping 10,000 times and sleeping 1 ms each time takes 20.00 seconds (instead of 10).</li><li>Looping 20,000 times and sleeping 1 ms each time takes 40.00 seconds (instead of 20).</li></ul><div>Up to 10,000 times it takes 12,16% (1/8) more time, from 10,000 times it takes 100% (double).</div></div><div><br></div><div>Can some kind soul explain what I'm doing wrong here and how to achieve the desired results?</div><div><br></div><div>I'm on OSX, Erlang 17.4.</div><div><br></div><div>Help! ^^_</div><span><font color="#888888"><div>r.</div><div><br></div></font></span></div>
</blockquote></div><br></div>
<br></div></div>_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
<br></blockquote></div>
</blockquote></div><br></div>
______________________________<u></u>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank">http://erlang.org/mailman/<u></u>listinfo/erlang-questions</a><br>
</blockquote></div>
</div></div><br>_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
<br></blockquote></div><br></div>
</div></div></blockquote></div><br></div>