Issue #8658 has been updated by jonforums (Jon Forums).


Eregon (Benoit Daloze) wrote:
> akr (Akira Tanaka) wrote:
> >  > While I appreciate Ruby is not always taking the lowest common denominator for functionality (fork, etc),
> >  > we need a counterpart for Windows and OS X at least.
> >  
> >  Users of such OSs can contribute an emulation function for clock_gettime.
> 
> A very poor one as mapping to Linux/UNIX constants would just confuse people.
> I do not think the UNIX API clock_gettime() for this is the most suitable,
> it does not abstract the functionality and the name/usage is not very ruby-like.
> 
> I think FFI would be a good way if someone need direct access to that low-level C function (except for accessing the constants, that would not be handy).
> 
> >  > naruse gave a very useful link in #8096, http://www.python.org/dev/peps/pep-0418/ .
> >  > I do not wish for a so large API, but I think we should have the timestamp functionality like time.time()
> >  > and a precise performance counter like time.perf_counter().
> >  
> >  PEP 0418 mentions that python provide clock_gettime as time.clock_gettime.
> >  PEP 0418 doesn't mean providing clock_gettime itself is bad idea.
> 
> I believe providing a method which is only available in a quite restricted set of platforms is to be avoided.
> In Python it is simply not defined on non-supporting platforms.
> 

It's great to see a focus on cross-platform impl issues :)

Has anyone spelunked libuv's awesomeness for inspiration on a nice cross-platform implementation style?

  # general header niceness
  https://github.com/joyent/libuv/blob/master/include/uv.h#L62-L67
    https://github.com/joyent/libuv/blob/master/include/uv-unix.h
    https://github.com/joyent/libuv/blob/master/include/uv-win.h

  # common timer API
  https://github.com/joyent/libuv/blob/master/include/uv.h#L1873-L1881

  # internal platform specific header timer niceness
  https://github.com/joyent/libuv/blob/master/src/unix/internal.h#L180-L181

  # platform specific impl niceness
  https://github.com/joyent/libuv/blob/master/src/win/util.c#L443-L465
  https://github.com/joyent/libuv/blob/master/src/unix/core.c#L78-L80
  https://github.com/joyent/libuv/blob/master/src/unix/linux-core.c#L245-L249
----------------------------------------
Feature #8658: Process.clock_gettime
https://bugs.ruby-lang.org/issues/8658#change-40627

Author: akr (Akira Tanaka)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


How about adding a new method, Process.clock_gettime(clk_id) ?

Recently there were two feature request for measuring time.
Feature #8640 https://bugs.ruby-lang.org/issues/8640
Feature #8096 https://bugs.ruby-lang.org/issues/8096

It seems they are somewhat different.

clock_gettime() function defined by POSIX is a good
candidate for providing as a method.
I think it can supports the both request.

Also, it has less possible design choices than the requests
because clock_gettime() is defined by POSIX.
People familiar to POSIX can learn the method more easily.

I wrote a patch to implement Process.clock_gettime.
This method can be used as follows.

  % ./ruby -e 'p Process.clock_gettime(Process::CLOCK_MONOTONIC)'
  2701692957811563

Several considerations:

I implemented the method as a module function of Process.
It is same as Process.times.
I expect clock_gettime is used mainly for measuring
time interval and wall clock time is not important.
So I didn't use Time.

The method returns a number of nanoseconds as an integer.
It is not so unexpected if user knows clock_gettime() in POSIX.

clock_gettime() returns it as struct timespec
which contains two fields: tv_sec and tv_nsec.

Although tv_sec is time_t, Time is not appropriate because
the origin (zero) can be other than the Epoch.
Actually CLOCK_MONOTONIC means elapsed time since
the system start-up time on Linux.

Also, I expect the result is subtracted in most case:
  t1 = Process.clock_gettime(...)
  ...
  t2 = Process.clock_gettime(...)
  t = t2 - t1
So the result should be easy to subtract.
An array such as [sec, nsec] is difficult to subtract.

The result is an integer, not a float.
IEEE 754 double is not enough to represent the result
of clock_gettime(CLOCK_REALTIME).
It contains 19 digits in decimal now but IEEE 754 double
can represent only 15 digits.

On LP64 systems, Fixnum can represent 2**62-1.
So (2**62-1)/(365.25*24*60*60*1e9)=146.1 years are representable
without object allocation.

On ILP32 and LLP64 systems, Fixnum can represent 2**30-1.
So (2**30-1)/1e9=1.07 seconds are representable
without object allocation.
This means Bignum allocations are mostly required except
the origin is very recent.

clock_gettime() is defined by POSIX.
Linux, NetBSD, FreeBSD, OpenBSD has it, at least.

If clock_gettime() is not available,
an emulation layer for CLOCK_REALTIME is implementable
using gettimeofday().
(not implemented yet, though.)

Any comments?



-- 
http://bugs.ruby-lang.org/