JDK-6868976 : Sequester os_solaris.cpp'max_hrtime to its own cache line
Type:Enhancement
Component:hotspot
Sub-Component:runtime
Affected Version:7
Priority:P3
Status:Resolved
Resolution:Duplicate
OS:solaris
CPU:generic
Submitted:2009-08-06
Updated:2014-12-10
Resolved:2014-06-04
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.
os_solaris.cpp'max_hrtime can become very hot -- placing it on its own cache line (and aligning to a 64-bit boundary on x86) should reduce interference wrt other data in the vicinity and improve performance.
Comments
Should we decide to isolate os_solaris.cpp:max_hrtime on its own cache
line sometime in the future, that code would look something like this:
$ hg diff src/os/solaris/vm/os_solaris.cpp
diff -r 35e222a277ba src/os/solaris/vm/os_solaris.cpp
--- a/src/os/solaris/vm/os_solaris.cpp Mon Dec 08 00:15:55 2014 -0800
+++ b/src/os/solaris/vm/os_solaris.cpp Tue Dec 09 17:00:09 2014 -0700
@@ -351,7 +351,14 @@ julong os::physical_memory() {
static hrtime_t first_hrtime = 0;
static const hrtime_t hrtime_hz = 1000*1000*1000;
-static volatile hrtime_t max_hrtime = 0;
+struct SharedGlobals {
+ char _pad_prefix[DEFAULT_CACHE_LINE_SIZE];
+ // Hot RW variable -- Sequester to avoid false-sharing
+ volatile hrtime_t max_hrtime;
+ DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile hrtime_t));
+};
+
+static SharedGlobals GVars;
void os::Solaris::initialize_system_info() {
@@ -1366,11 +1373,13 @@ void* os::thread_local_storage_at(int in
// are forced to add a check here.
inline hrtime_t getTimeNanos() {
const hrtime_t now = gethrtime();
- const hrtime_t prev = max_hrtime;
+ const hrtime_t prev = GVars.max_hrtime;
if (now <= prev) {
return prev; // same or retrograde time;
}
- const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
+ const hrtime_t obsv = Atomic::cmpxchg(now,
+ (volatile jlong*)&GVars.max_hrtime,
+ prev);
assert(obsv >= prev, "invariant"); // Monotonicity
// If the CAS succeeded then we're done and return "now".
// If the CAS failed and the observed value "obsv" is >= now then
@@ -4534,7 +4543,7 @@ void os::init(void) {
void os::init(void) {
_initial_pid = getpid();
- max_hrtime = first_hrtime = gethrtime();
+ GVars.max_hrtime = first_hrtime = gethrtime();
init_random(1234567);
10-12-2014
The issue described in this bug where addressed with the fix of JDK-8040140
04-06-2014
There have been two changes to the code that reduced the cache line contention for max_hrtime.
The most significant change is JDK-8040140 https://bugs.openjdk.java.net/browse/JDK-8040140
This change removed the need for max_hrtime_lock variable. Since max_hrtime_lock probably shared the same cache line as max_hrtime,
removing it removed contention from the same cache line as max_hrtime. The change also removed support for oldgetTimeNanos() that was used for
older architectures that did not support cx8. oldgetTimeNanos() called Atomic::cmpxchg() within a for loop that also increased contention.
Staffan provided detailed performance testing that showed improved performance after the change.
Another related change was JDK-6784100 https://bugs.openjdk.java.net/browse/JDK-6784100
This change reduced the coherency traffic related to max_hrtime by removing a while loop that could introduce
multiple Atomic::cmpxchg() calls using max_hrtime.
Support for cx8 features on all solaris platforms and the two changes mentioned above has removed the need for max_hrtime to be moved to its own cache line.