JDK-8154710 : [Solaris] Investigate use of in-memory low-resolution timestamps for Java and internal time API's
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_11
  • Submitted: 2016-04-20
  • Updated: 2019-01-21
  • Resolved: 2016-05-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b120Fixed
Related Reports
Relates :  
Description
As of Solaris 11.3(SRU6) low-resolution in-memory timestamps are available through a new API. This is essentially a set of timestamps in memory that are updated once per millisecond. Access to these timestamps should be very quick and so may be a good replacement for the low-resolution time API's in the VM that currently use gettimeofday.

Need to investigate how these new calls perform and if they are suitable replacements.

Comments
Note this change was reverted under JDK-8157175 as the API cannot be used. We have two time functions that must use the same source, and for which 1ms accuracy is not sufficient for one of them.
21-01-2019

Note that only System.currentTimeMillis() is affected by this change - which of course should not be at all observable other than through performance measures. All other internal and external time API's need better than 1ms accuracy.
28-04-2016

Here's a simple test program, a.k.a microbenchmark, to measure the costs for a million calls to get the current milliseconds since the epoch, using the two different techniques: /* measuretod.cpp */ #include <sys/types.h> #include <sys/system_stats.h> #include <stdio.h> #define ITERS 1000000 static unsigned long long cur_time; void measure_get_nsec_fromepoch() { const hrtime_t start = gethrtime(); for (int i = 0; i < ITERS; i++) { hrtime_t now; get_nsec_fromepoch(&now); cur_time = now / (1000 * 1000); } const hrtime_t end = gethrtime(); hrtime_t elapsed = end - start; unsigned long long nanos_per_op = elapsed/ITERS; printf("get_nsec_fromepoch(): %llu nanos/op\n", nanos_per_op); printf("cur_time: %llu\n", cur_time); } void measure_gettimeofday() { const hrtime_t start = gethrtime(); for (int i = 0; i < ITERS; i++) { timeval t; gettimeofday(&t, NULL); cur_time = ((unsigned long long)(t.tv_sec)) * 1000 + ((unsigned long long)(t.tv_usec)) / 1000; } const hrtime_t end = gethrtime(); hrtime_t elapsed = end - start; unsigned long long nanos_per_op = elapsed/ITERS; printf("gettimeofday(): %llu nanos/op\n", nanos_per_op); printf("cur_time: %llu\n", cur_time); } int main(int argc, char* argv[]) { measure_get_nsec_fromepoch(); measure_gettimeofday(); measure_get_nsec_fromepoch(); measure_gettimeofday(); measure_get_nsec_fromepoch(); measure_gettimeofday(); } ----------------- The compile command (note 32-bit is slower than 64-bit): CC -o measuretod -m64 measuretod.cpp Results: > ./measuretod get_nsec_fromepoch(): 19 nanos/op cur_time: 1461729831475 gettimeofday(): 35 nanos/op cur_time: 1461729831512 get_nsec_fromepoch(): 19 nanos/op cur_time: 1461729831543 gettimeofday(): 35 nanos/op cur_time: 1461729831579 get_nsec_fromepoch(): 19 nanos/op cur_time: 1461729831611 gettimeofday(): 35 nanos/op cur_time: 1461729831646 So we have basically 19ns vs 35ns which seems like a good win. We have to offset that with a small startup penalty for dynamically locating the function, and a small runtime overhead to select which technique to use, but it seems like a worthwhile change for javaTimeMillis (which backs System.currentTimeMillis()).
27-04-2016

Man pages are missing in 11.3 here's the text: NAME get_hrusec, get_sec_fromepoch, get_nsec_fromepoch . SYNOPSIS #include <sys/types.h> #include <sys/system_stats.h> . void get_hrusec(hrtime_t *usec); . void get_sec_fromepoch(memtime_sec_t *sec); . void get_nsec_fromepoch(hrtime_t *nsec); . . DESCRIPTION These functions are provided for performance reasons. The overhead of reading time using these functions is minimum as they return time read from memory. No system calls are involved in get_* functions. . The get_hrusec() function returns high-resolution real time which is expressed as microseconds since some arbitrary time in the past. It is not correlated in any way to the time of day, and thus is not subject to resetting or drifting by way of adjtime(2) or settimeof- day(3C). This high-resolution time is suited for performance measurement. Although the best time accuracy it gives is 1 millisecond unlike gethrtime(3C). . The get_sec_fromepoch() and get_nsec_fromepoch returns time expressed in elapsed seconds from epoch(January 1, 1970) and elapsed nanoseconds from epoch respectively. Time returned by both these functions are subject to setting or drifting by adjtime(2) or settimeofday(3C) calls. . Note, the accuracy of nsecs returned by get_nsec_fromepoch() is 1 millisecond.
26-04-2016