RFR: 8186670: Implement _onSpinWait() intrinsic for AArch64 [v13]
Andrew Haley
aph at openjdk.java.net
Mon Nov 1 13:15:14 UTC 2021
On Thu, 21 Oct 2021 15:19:47 GMT, Evgeny Astigeevich <duke at openjdk.java.net> wrote:
>> Looks good. I'm not entirely sure whether this test is truly representative of the real-world cases that people have seen, but if we find out more we can always add another JMH test.
>
> This test is too artificial. Going through my records I've found I have a microbenchmark for `java.util.concurrent. SynchronousQueue` which shows good improvements on jdk11. `SynchronousQueue` uses `onSpinWait`. Since jdk17 `SynchronousQueue` has not been using `onSpinWait` any more (See https://bugs.openjdk.java.net/browse/JDK-8267502). Maybe I can come up with a microbenchmark based on `SynchronousQueue` [code](https://github.com/openjdk/jdk11u-dev/blob/master/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java#L412):
>
> SNode awaitFulfill(SNode s, boolean timed, long nanos) {
> /*
> * When a node/thread is about to block, it sets its waiter
> * field and then rechecks state at least one more time
> * before actually parking, thus covering race vs
> * fulfiller noticing that waiter is non-null so should be
> * woken.
> *
> * When invoked by nodes that appear at the point of call
> * to be at the head of the stack, calls to park are
> * preceded by spins to avoid blocking when producers and
> * consumers are arriving very close in time. This can
> * happen enough to bother only on multiprocessors.
> *
> * The order of checks for returning out of main loop
> * reflects fact that interrupts have precedence over
> * normal returns, which have precedence over
> * timeouts. (So, on timeout, one last check for match is
> * done before giving up.) Except that calls from untimed
> * SynchronousQueue.{poll/offer} don't check interrupts
> * and don't wait at all, so are trapped in transfer
> * method rather than calling awaitFulfill.
> */
> final long deadline = timed ? System.nanoTime() + nanos : 0L;
> Thread w = Thread.currentThread();
> int spins = shouldSpin(s)
> ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
> : 0;
> for (;;) {
> if (w.isInterrupted())
> s.tryCancel();
> SNode m = s.match;
> if (m != null)
> return m;
> if (timed) {
> nanos = deadline - System.nanoTime();
> if (nanos <= 0L) {
> s.tryCancel();
> continue;
> }
> }
> if (spins > 0) {
> Thread.onSpinWait();
> spins = shouldSpin(s) ? (spins - 1) : 0;
> }
> else if (s.waiter == null)
> s.waiter = w; // establish waiter so can park next iter
> else if (!timed)
> LockSupport.park(this);
> else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
> LockSupport.parkNanos(this, nanos);
> }
> }
>
>
> I've created https://bugs.openjdk.java.net/browse/JDK-8275728 to write such a microbenchmark.
I suggest you do https://bugs.openjdk.java.net/browse/JDK-8275728 before you commit this. A benchmark which proves that this patch has some utility is needed, isn't it?
-------------
PR: https://git.openjdk.java.net/jdk/pull/5562
More information about the hotspot-dev
mailing list