This is blog 5 in the OpenJ9 locking/synchronization series (blog 1). This blog covers OpenJ9’s adaptive spinning strategy which dynamically enables/disables lock spinning using heuristics in order to avoid the negative impact of lock spinning. Before reading this blog, one needs to know about the system-monitors (blog 2), object-monitors (blog 3) and three-tier spinning (blog 4). Please read the aforementioned blogs before reading this blog.
At multiple occasions, it was noticed that the CPU cycles consumed by lock spinning decreased the performance of an application. In some of these poor cases, it was found that disabling spinning improves performance. The impact of disabling spinning varies by platform.
The adaptive spinning strategy identifies the cases where spinning i) is useful and ii) consumes CPU cycles that could be better used by the application.
For example, if a lock has an average hold time of 1 second, then with the current spin settings it is unlikely that spinning will help as the spin time is much shorter than the average lock hold time. So, the spin cycles are simply wasted.
Adaptive spinning identifies the locks where spinning is not helpful, and enables/disables spinning for those locks as needed.
The lock information is recorded at the system-monitor level. Spinning is disabled at all levels, when it is decided to disable spinning. When spinning is disabled for a system-monitor which is backing an object-monitor, then spinning is disabled for both the object-monitor and system-monitor. Spinning is disabled by
- Setting all the spin control parameters for the system-monitor to 1 (threeTierSpinCount1, threeTierSpinCount2, threeTierSpinCount3)
- Preventing the object monitor from being deflated and setting the J9THREAD_MONITOR_DISABLE_SPINNING in system-monitor’s flag field.
It might be better to disable spinning in the flat lock mode for the object monitor instead of preventing deflation but this would require additional information in the lock-word in addition to the inflation bit.
The adaptive spinning feature relies upon the below heuristics to disable spinning:
|holdtime||Disable spinning if average hold time for a lock is longer than X.|
|slow percent||Disable spinning if percent of slow GETS versus overall GETS is greater than Y.|
The adaptive spinning feature can be controlled via the following command line options:
|[a/noA]daptSpin||Enable/disable adaptive spinning.|
|adaptSpinHoldtime||Threshold used in hold-time heuristic.|
|adaptSpinSlowPercent||Threshold used in the slow percent heuristic.|
|adaptSpinSample*||Control the frequency of data (lock statistics) collection. Note: the counters are only incremented when a lock is acquired at the system-monitor level. If a lock is acquired through spinning at the object monitor level, then the counters are not incremented.|
|adaptSpin[No]KeepSampling||Enable or disable the sampling of lock statistics once spinning is disabled.|
An example of using the above command line options:
java -Xthr:adaptSpin,adaptSpinHoldtime=<...>,adaptSpinSlowPercent=<...>,adaptSpinSampleThreshhold=<...>,adaptSpinSampleStopCount=<...>,adaptSpinSampleCountStopRatio=<...>,adaptSpinKeepSampling,what ...
The default values for the adaptive spinning command line options are:
Adaptive spinning currently piggy backs on the JLM infrastructure but has lower overhead because the adaptSpinSample* options reduce the frequency of data collection. The JLM infrastructure profiles and records monitor properties periodically. J9ThreadMonitorTracing is the data-structure which contains the monitor properties. This data-structure is updated in each three-tier spin loop, and it is also updated during monitor enter, wait and exit operations.
- All the code related to adaptive spinning can be found by querying OMR_THR_ADAPTIVE_SPIN in the OpenJ9 and OMR codebases.
- The command line options for adaptive spinning are parsed in vmthread.c (OpenJ9).
Functionality for adaptive spinning:
- ADAPT_DISABLE_SPIN_CHECK (disables and enables spinning based upon heuristics)
- Other macros for adaptive spinning are defined in threaddef.h (OMR).
Places where J9ThreadMonitorTracing structures (JLM data) are updated:
- UPDATE_JLM_MON_ENTER (calls ADAPT_DISABLE_SPIN_CHECK and is called from omrthread_monitor_enter)
- UPDATE_JLM_MON_EXIT (called from omrthread_monitor_exit)
- UPDATE_JLM_MON_WAIT (called from omrthread_monitor_wait)
Places where adaptive spinning enables/disables spinning:
The next blog in the OpenJ9 locking/synchronization series covers OpenJ9’s lock nursery (blog 6) feature, which reduces the memory usage by optimizing the memory allocation for the object-monitors’ lock-words.
[Note] Not all the command line options mentioned above may have customer support. Some options are only available for experimental work.