Handling of onSpinWait and its absence in AffinityPool (#28946)

This commit is contained in:
Viktor Klang (√) 2020-04-29 18:08:05 +00:00 committed by GitHub
parent 03411dd3cd
commit a910bee99f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 15 deletions

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2009-2020 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.dispatch.affinity;
import akka.util.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import akka.annotation.InternalApi;
import static java.lang.invoke.MethodType.methodType;
/**
* INTERNAL API
*/
@InternalApi
final class OnSpinWait {
private final static MethodHandle handle;
public final static void spinWait() throws Throwable {
handle.invoke(); // Will be inlined as an invokeExact since the callsite matches the MH definition of () -> void
}
static {
final MethodHandle noop = MethodHandles.constant(Object.class, null).asType(methodType(Void.TYPE));
MethodHandle impl;
try {
impl = MethodHandles.lookup().findStatic(Thread.class, "onSpinWait", methodType(Void.TYPE));
} catch (NoSuchMethodException nsme) {
impl = noop;
} catch (IllegalAccessException iae) {
impl = noop;
}
handle = impl;
};
}

View file

@ -5,8 +5,6 @@
package akka.dispatch.affinity
import java.lang.Integer.reverseBytes
import java.lang.invoke.MethodHandles
import java.lang.invoke.MethodType.methodType
import java.util.Collections
import java.util.concurrent._
import java.util.concurrent.TimeUnit.MICROSECONDS
@ -15,16 +13,18 @@ import java.util.concurrent.locks.LockSupport
import scala.annotation.{ switch, tailrec }
import scala.collection.{ immutable, mutable }
import scala.util.control.NonFatal
import com.typesafe.config.Config
import akka.annotation.{ ApiMayChange, InternalApi }
import akka.dispatch._
import akka.event.Logging
import akka.util.{ ImmutableIntMap, OptionVal, ReentrantGuard }
import akka.util.{ ImmutableIntMap, ReentrantGuard }
import akka.util.Helpers.Requiring
import scala.annotation.{ switch, tailrec }
import scala.collection.{ immutable, mutable }
@InternalApi
@ApiMayChange
private[affinity] object AffinityPool {
@ -42,13 +42,6 @@ private[affinity] object AffinityPool {
// PoolState: all threads have been stopped, does not process tasks and does not accept new ones
final val Terminated = 5
// Method handle to JDK9+ onSpinWait method
private val onSpinWaitMethodHandle =
try OptionVal.Some(MethodHandles.lookup.findStatic(classOf[Thread], "onSpinWait", methodType(classOf[Void])))
catch {
case NonFatal(_) => OptionVal.None
}
type IdleState = Int
// IdleState: Initial state
final val Initial = 0
@ -85,10 +78,7 @@ private[affinity] object AffinityPool {
idling = true
transitionTo(Spinning)
case Spinning =>
onSpinWaitMethodHandle match {
case OptionVal.Some(m) => m.invokeExact()
case OptionVal.None =>
}
OnSpinWait.spinWait()
turns += 1
if (turns > maxSpins)
transitionTo(Yielding)