Method: Process#clock_gettime
- Defined in:
- process.c
#clock_gettime(clock_id, unit = :float_second) ⇒ Numeric (private)
Returns a clock time as determined by POSIX function clock_gettime():
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID) # => 198.650379677
Argument clock_id
should be a symbol or a constant that specifies the clock whose time is to be returned; see below.
Optional argument unit
should be a symbol that specifies the unit to be used in the returned clock time; see below.
Argument clock_id
Argument clock_id
specifies the clock whose time is to be returned; it may be a constant such as Process::CLOCK_REALTIME
, or a symbol shorthand such as :CLOCK_REALTIME
.
The supported clocks depend on the underlying operating system; this method supports the following clocks on the indicated platforms (raises Errno::EINVAL if called with an unsupported clock):
-
:CLOCK_BOOTTIME
: Linux 2.6.39. -
:CLOCK_BOOTTIME_ALARM
: Linux 3.0. -
:CLOCK_MONOTONIC
: SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12, Windows-2000. -
:CLOCK_MONOTONIC_COARSE
: Linux 2.6.32. -
:CLOCK_MONOTONIC_FAST
: FreeBSD 8.1. -
:CLOCK_MONOTONIC_PRECISE
: FreeBSD 8.1. -
:CLOCK_MONOTONIC_RAW
: Linux 2.6.28, macOS 10.12. -
:CLOCK_MONOTONIC_RAW_APPROX
: macOS 10.12. -
:CLOCK_PROCESS_CPUTIME_ID
: SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12. -
:CLOCK_PROF
: FreeBSD 3.0, OpenBSD 2.1. -
:CLOCK_REALTIME
: SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012. Time.now is recommended over +:CLOCK_REALTIME:. -
:CLOCK_REALTIME_ALARM
: Linux 3.0. -
:CLOCK_REALTIME_COARSE
: Linux 2.6.32. -
:CLOCK_REALTIME_FAST
: FreeBSD 8.1. -
:CLOCK_REALTIME_PRECISE
: FreeBSD 8.1. -
:CLOCK_SECOND
: FreeBSD 8.1. -
:CLOCK_TAI
: Linux 3.10. -
:CLOCK_THREAD_CPUTIME_ID
: SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12. -
:CLOCK_UPTIME
: FreeBSD 7.0, OpenBSD 5.5. -
:CLOCK_UPTIME_FAST
: FreeBSD 8.1. -
:CLOCK_UPTIME_PRECISE
: FreeBSD 8.1. -
:CLOCK_UPTIME_RAW
: macOS 10.12. -
:CLOCK_UPTIME_RAW_APPROX
: macOS 10.12. -
:CLOCK_VIRTUAL
: FreeBSD 3.0, OpenBSD 2.1.
Note that SUS stands for Single Unix Specification. SUS contains POSIX and clock_gettime is defined in the POSIX part. SUS defines :CLOCK_REALTIME
as mandatory but :CLOCK_MONOTONIC
, :CLOCK_PROCESS_CPUTIME_ID
, and :CLOCK_THREAD_CPUTIME_ID
are optional.
Certain emulations are used when the given clock_id
is not supported directly:
-
Emulations for
:CLOCK_REALTIME
:-
:GETTIMEOFDAY_BASED_CLOCK_REALTIME
: Use gettimeofday() defined by SUS (deprecated in SUSv4). The resolution is 1 microsecond. -
:TIME_BASED_CLOCK_REALTIME
: Use time() defined by ISO C. The resolution is 1 second.
-
-
Emulations for
:CLOCK_MONOTONIC
:-
:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
: Use mach_absolute_time(), available on Darwin. The resolution is CPU dependent. -
:TIMES_BASED_CLOCK_MONOTONIC
: Use the result value of times() defined by POSIX, thus:Upon successful completion, times() shall return the elapsed real time, in clock ticks, since an arbitrary point in the past (for example, system start-up time).
For example, GNU/Linux returns a value based on jiffies and it is monotonic. However, 4.4BSD uses gettimeofday() and it is not monotonic. (FreeBSD uses
:CLOCK_MONOTONIC
instead, though.)The resolution is the clock tick. “getconf CLK_TCK” command shows the clock ticks per second. (The clock ticks-per-second is defined by HZ macro in older systems.) If it is 100 and clock_t is 32 bits integer type, the resolution is 10 millisecond and cannot represent over 497 days.
-
-
Emulations for
:CLOCK_PROCESS_CPUTIME_ID
:-
:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
: Use getrusage() defined by SUS. getrusage() is used with RUSAGE_SELF to obtain the time only for the calling process (excluding the time for child processes). The result is addition of user time (ru_utime) and system time (ru_stime). The resolution is 1 microsecond. -
:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
: Use times() defined by POSIX. The result is addition of user time (tms_utime) and system time (tms_stime). tms_cutime and tms_cstime are ignored to exclude the time for child processes. The resolution is the clock tick. “getconf CLK_TCK” command shows the clock ticks per second. (The clock ticks per second is defined by HZ macro in older systems.) If it is 100, the resolution is 10 millisecond. -
:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
: Use clock() defined by ISO C. The resolution is1/CLOCKS_PER_SEC
.CLOCKS_PER_SEC
is the C-level macro defined by time.h. SUS definesCLOCKS_PER_SEC
as 1000000; other systems may define it differently. IfCLOCKS_PER_SEC
is 1000000 (as in SUS), the resolution is 1 microsecond. IfCLOCKS_PER_SEC
is 1000000 and clock_t is a 32-bit integer type, it cannot represent over 72 minutes.
-
Argument unit
Optional argument unit
(default :float_second
) specifies the unit for the returned value.
-
:float_microsecond
: Number of microseconds as a float. -
:float_millisecond
: Number of milliseconds as a float. -
:float_second
: Number of seconds as a float. -
:microsecond
: Number of microseconds as an integer. -
:millisecond
: Number of milliseconds as an integer. -
:nanosecond
: Number of nanoseconds as an integer. -
::second
: Number of seconds as an integer.
Examples:
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond)
# => 203605054.825
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond)
# => 203643.696848
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_second)
# => 203.762181929
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :microsecond)
# => 204123212
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :millisecond)
# => 204298
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond)
# => 204602286036
Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :second)
# => 204
The underlying function, clock_gettime(), returns a number of nanoseconds. Float object (IEEE 754 double) is not enough to represent the return value for :CLOCK_REALTIME
. If the exact nanoseconds value is required, use :nanosecond
as the unit
.
The origin (time zero) of the returned value is system-dependent, and may be, for example, system start up time, process start up time, the Epoch, etc.
The origin in :CLOCK_REALTIME
is defined as the Epoch: 1970-01-01 00:00:00 UTC
; some systems count leap seconds and others don’t, so the result may vary across systems.
8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 |
# File 'process.c', line 8360
static VALUE
rb_clock_gettime(int argc, VALUE *argv, VALUE _)
{
int ret;
struct timetick tt;
timetick_int_t numerators[2];
timetick_int_t denominators[2];
int num_numerators = 0;
int num_denominators = 0;
VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
VALUE clk_id = argv[0];
#ifdef HAVE_CLOCK_GETTIME
clockid_t c;
#endif
if (SYMBOL_P(clk_id)) {
#ifdef CLOCK_REALTIME
if (clk_id == RUBY_CLOCK_REALTIME) {
c = CLOCK_REALTIME;
goto gettime;
}
#endif
#ifdef CLOCK_MONOTONIC
if (clk_id == RUBY_CLOCK_MONOTONIC) {
c = CLOCK_MONOTONIC;
goto gettime;
}
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
if (clk_id == RUBY_CLOCK_PROCESS_CPUTIME_ID) {
c = CLOCK_PROCESS_CPUTIME_ID;
goto gettime;
}
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
if (clk_id == RUBY_CLOCK_THREAD_CPUTIME_ID) {
c = CLOCK_THREAD_CPUTIME_ID;
goto gettime;
}
#endif
/*
* Non-clock_gettime clocks are provided by symbol clk_id.
*/
#ifdef HAVE_GETTIMEOFDAY
/*
* GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
* CLOCK_REALTIME if clock_gettime is not available.
*/
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
struct timeval tv;
ret = gettimeofday(&tv, 0);
if (ret != 0)
rb_sys_fail("gettimeofday");
tt.giga_count = tv.tv_sec;
tt.count = (int32_t)tv.tv_usec * 1000;
denominators[num_denominators++] = 1000000000;
goto success;
}
#endif
#define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
time_t t;
t = time(NULL);
if (t == (time_t)-1)
rb_sys_fail("time");
tt.giga_count = t;
tt.count = 0;
denominators[num_denominators++] = 1000000000;
goto success;
}
#ifdef HAVE_TIMES
#define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC)
if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
struct tms buf;
clock_t c;
unsigned_clock_t uc;
c = times(&buf);
if (c == (clock_t)-1)
rb_sys_fail("times");
uc = (unsigned_clock_t)c;
tt.count = (int32_t)(uc % 1000000000);
tt.giga_count = (uc / 1000000000);
denominators[num_denominators++] = get_clk_tck();
goto success;
}
#endif
#ifdef RUSAGE_SELF
#define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
struct rusage usage;
int32_t usec;
ret = getrusage(RUSAGE_SELF, &usage);
if (ret != 0)
rb_sys_fail("getrusage");
tt.giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
if (1000000 <= usec) {
tt.giga_count++;
usec -= 1000000;
}
tt.count = usec * 1000;
denominators[num_denominators++] = 1000000000;
goto success;
}
#endif
#ifdef HAVE_TIMES
#define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID)
if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
struct tms buf;
unsigned_clock_t utime, stime;
if (times(&buf) == (clock_t)-1)
rb_sys_fail("times");
utime = (unsigned_clock_t)buf.tms_utime;
stime = (unsigned_clock_t)buf.tms_stime;
tt.count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
tt.giga_count = (utime / 1000000000) + (stime / 1000000000);
if (1000000000 <= tt.count) {
tt.count -= 1000000000;
tt.giga_count++;
}
denominators[num_denominators++] = get_clk_tck();
goto success;
}
#endif
#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID)
if (clk_id == RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
clock_t c;
unsigned_clock_t uc;
errno = 0;
c = clock();
if (c == (clock_t)-1)
rb_sys_fail("clock");
uc = (unsigned_clock_t)c;
tt.count = (int32_t)(uc % 1000000000);
tt.giga_count = uc / 1000000000;
denominators[num_denominators++] = CLOCKS_PER_SEC;
goto success;
}
#ifdef __APPLE__
if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
const mach_timebase_info_data_t *info = get_mach_timebase_info();
uint64_t t = mach_absolute_time();
tt.count = (int32_t)(t % 1000000000);
tt.giga_count = t / 1000000000;
numerators[num_numerators++] = info->numer;
denominators[num_denominators++] = info->denom;
denominators[num_denominators++] = 1000000000;
goto success;
}
#endif
}
else if (NUMERIC_CLOCKID) {
#if defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
c = NUM2CLOCKID(clk_id);
gettime:
ret = clock_gettime(c, &ts);
if (ret == -1)
clock_failed("gettime", errno, clk_id);
tt.count = (int32_t)ts.tv_nsec;
tt.giga_count = ts.tv_sec;
denominators[num_denominators++] = 1000000000;
goto success;
#endif
}
else {
rb_unexpected_type(clk_id, T_SYMBOL);
}
clock_failed("gettime", EINVAL, clk_id);
success:
return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
}
|