Handling of onSpinWait and its absence in AffinityPool (#28946)
This commit is contained in:
parent
03411dd3cd
commit
a910bee99f
2 changed files with 41 additions and 15 deletions
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
package akka.dispatch.affinity
|
package akka.dispatch.affinity
|
||||||
|
|
||||||
import java.lang.Integer.reverseBytes
|
import java.lang.Integer.reverseBytes
|
||||||
import java.lang.invoke.MethodHandles
|
|
||||||
import java.lang.invoke.MethodType.methodType
|
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.concurrent._
|
import java.util.concurrent._
|
||||||
import java.util.concurrent.TimeUnit.MICROSECONDS
|
import java.util.concurrent.TimeUnit.MICROSECONDS
|
||||||
|
|
@ -15,16 +13,18 @@ import java.util.concurrent.locks.LockSupport
|
||||||
|
|
||||||
import scala.annotation.{ switch, tailrec }
|
import scala.annotation.{ switch, tailrec }
|
||||||
import scala.collection.{ immutable, mutable }
|
import scala.collection.{ immutable, mutable }
|
||||||
import scala.util.control.NonFatal
|
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
|
||||||
import akka.annotation.{ ApiMayChange, InternalApi }
|
import akka.annotation.{ ApiMayChange, InternalApi }
|
||||||
import akka.dispatch._
|
import akka.dispatch._
|
||||||
import akka.event.Logging
|
import akka.event.Logging
|
||||||
import akka.util.{ ImmutableIntMap, OptionVal, ReentrantGuard }
|
import akka.util.{ ImmutableIntMap, ReentrantGuard }
|
||||||
import akka.util.Helpers.Requiring
|
import akka.util.Helpers.Requiring
|
||||||
|
|
||||||
|
import scala.annotation.{ switch, tailrec }
|
||||||
|
import scala.collection.{ immutable, mutable }
|
||||||
|
|
||||||
@InternalApi
|
@InternalApi
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
private[affinity] object AffinityPool {
|
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
|
// PoolState: all threads have been stopped, does not process tasks and does not accept new ones
|
||||||
final val Terminated = 5
|
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
|
type IdleState = Int
|
||||||
// IdleState: Initial state
|
// IdleState: Initial state
|
||||||
final val Initial = 0
|
final val Initial = 0
|
||||||
|
|
@ -85,10 +78,7 @@ private[affinity] object AffinityPool {
|
||||||
idling = true
|
idling = true
|
||||||
transitionTo(Spinning)
|
transitionTo(Spinning)
|
||||||
case Spinning =>
|
case Spinning =>
|
||||||
onSpinWaitMethodHandle match {
|
OnSpinWait.spinWait()
|
||||||
case OptionVal.Some(m) => m.invokeExact()
|
|
||||||
case OptionVal.None =>
|
|
||||||
}
|
|
||||||
turns += 1
|
turns += 1
|
||||||
if (turns > maxSpins)
|
if (turns > maxSpins)
|
||||||
transitionTo(Yielding)
|
transitionTo(Yielding)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue