erlang / otp

Erlang/OTP
http://erlang.org
Apache License 2.0
11.39k stars 2.96k forks source link

ERL-608: Better time handling (grabbing native time unit/ timer.tc variant/alternative) #3264

Closed OTP-Maintainer closed 1 year ago

OTP-Maintainer commented 6 years ago

Original reporter: pragtob Affected version: Not Specified Component: Not Specified Migrated from: https://bugs.erlang.org/browse/ERL-608


(first thanks for Erlang et. al. <3)

 I have a suggestion for making time measurements better/more accurate. The normal built-in way to measure function execution time is [timer.tc/n|http://erlang.org/doc/man/timer.html#tc-1] but as described in its documentation and implemented it [always returns|https://github.com/erlang/otp/blob/master/lib/stdlib/src/timer.erl#L164-L169].

However, for instance on my Linux system the time measuring according to `erts_internal:time_unit/0` is nano seconds so precision is given up.

One could just reimplement timer.tc but without knowing what time unit monotonic_time returns it's hard as usage of erts_internal functions is clearly discouraged. Making the "native" time unit part of the public API would probably be the easiest fix. 

(There are workarounds like converting the monotonic time returned to another unit until you figure out the unit where it doesn't change).

Another idea would to offer an alternative to timer.tc that doesn't only return the time but the (native) unit it was measured in as well. So instead of {1000, result} the return value might be {{1000, microscond}, result}.

That'd be great and I think would help people who want to casually measure execution times (for logging purposes) or do more advanced things with them.

(I maintain a benchmarking library on the BEAM and stumbled across this as the native unit on Windows seems to be milliseconds which was a surprise to us)

Sorry if I didn't fill out some fields I should have.
OTP-Maintainer commented 6 years ago

rickard said:

{quote}
One could just reimplement timer.tc but without knowing what time unit monotonic_time returns it's hard as usage of erts_internal functions is clearly discouraged. Making the "native" time unit part of the public API would probably be the easiest fix. 
{quote}

Changing the time unit of the value returned to {{native}} time unit is not a viable option, since that would break backwards compatibility.

A note on {{erts_internal:time_unit/0}}. It is intentionally not part of the API since we want the possibility to use time units that cannot be represented as whole units per second in the future. If you want an approximation of the {{native}} time unit you can utilize [{{erlang:convert_time_unit(1, second, native)}}|http://erlang.org/doc/man/erlang.html#convert_time_unit-3]. For more info see documentation of the [{{erlang:time_unit()}}|http://erlang.org/doc/man/erlang.html#type-time_unit] type.

{quote}
Another idea would to offer an alternative to timer.tc that doesn't only return the time but the (native) unit it was measured in as well. So instead of  {1000, result}
{quote}

An extended {{timer:tc()}} with a time unit argument determining the time unit to use would be preferred:
{code}
tc(Fun) -> {Time, Value}
tc(Fun, Arguments) -> {Time, Value}
tc(Module, Function, Arguments) -> {Time, Value}
tc(Fun, TimeUnit) -> {TuTime, Value}
tc(Fun, Arguments, TimeUnit) -> {TuTime, Value}
tc(Module, Function, Arguments, TimeUnit) -> {TuTime, Value}
  Types:
    Module = module()
    Function = atom()
    Arguments = [term()]
    Time = integer()
        In microseconds
    Value = term()
    TimeUnit = erlang:time_unit()
    TuTime = integer()
        In TimeUnit
{code}

This is not high prio for us though, so we will currently not implement this, but might in the future. A pull request implementing this would however be welcome.

{quote}
(I maintain a benchmarking library on the BEAM and stumbled across this as the native unit on Windows seems to be milliseconds which was a surprise to us)
{quote}

The resolution on windows is even worse than that. The source is {{GetTickCount()}}/{{GetTickCount64()}} which have a resolution of 16ms if I remember correct.

We have had plans for usage of {{QueryPerformanceCounter}} instead, but it has issues with monotonicity which we have to solve in order to be able to use it. This makes the whole thing quite a bit more complex than it otherwise would have been. This work has not had high enough prio for us to work on yet.

You can utilize [{{erlang:system_info(os_monotonic_time_source)}}|http://erlang.org/doc/man/erlang.html#system_info_os_monotonic_time_source] in order to get information about the monotonic time source on your system.
rickard-green commented 1 year ago

Implemented by #6507 which has been merged into master (to be released in OTP 26)