Uploaded image for project: 'Erlang/OTP'
  1. Erlang/OTP
  2. ERL-608

Better time handling (grabbing native time unit/ timer.tc variant/alternative)

    Details

    • Type: Improvement
    • Status: Help Wanted
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      (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 but as described in its documentation and implemented it always returns.

      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.

        Activity

        Hide
        rickard Rickard Green added a comment - - edited

        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.

        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). For more info see documentation of the erlang:time_unit() type.

        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

        Unknown macro: {1000, result}

        An extended timer:tc() with a time unit argument determining the time unit to use would be preferred:

        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
        

        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.

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

        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) in order to get information about the monotonic time source on your system.

        Show
        rickard Rickard Green added a comment - - edited 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. 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) . For more info see documentation of the erlang:time_unit() type. 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 Unknown macro: {1000, result} An extended timer:tc() with a time unit argument determining the time unit to use would be preferred: 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 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. (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) 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) in order to get information about the monotonic time source on your system.

          People

          • Assignee:
            otp_team_vm Team VM
            Reporter:
            PragTob Tobias Pfeiffer
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:

              Development