From: "jonforums (Jon Forums)" Date: 2013-07-24T03:14:38+09:00 Subject: [ruby-core:56133] [ruby-trunk - Feature #8658] Process.clock_gettime 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/