=act #16522 Optimize Stash creation
* cache the stash capacity config value
BEFORE
[info] Result "testCustom":
[info] 27.607 ±(99.9%) 7.924 us/op [Average]
[info] (min, avg, max) = (16.928, 27.607, 760217.600), stdev = 1369.808
[info] CI (99.9%): [19.682, 35.531] (assumes normal distribution)
[info] Samples, N = 323534
[info] mean = 27.607 ±(99.9%) 7.924 us/op
[info] min = 16.928 us/op
[info] p( 0.0000) = 16.928 us/op
[info] p(50.0000) = 21.824 us/op
[info] p(90.0000) = 31.680 us/op
[info] p(95.0000) = 38.592 us/op
[info] p(99.0000) = 57.920 us/op
[info] p(99.9000) = 102.144 us/op
[info] p(99.9900) = 371.471 us/op
[info] p(99.9990) = 85461.364 us/op
[info] p(99.9999) = 760217.600 us/op
[info] max = 760217.600 us/op
[info] Result "testDefault":
[info] 26.465 ±(99.9%) 15.980 us/op [Average]
[info] (min, avg, max) = (14.608, 26.465, 1461714.944), stdev = 2900.094
[info] CI (99.9%): [10.485, 42.444] (assumes normal distribution)
[info] Samples, N = 356626
[info] mean = 26.465 ±(99.9%) 15.980 us/op
[info] min = 14.608 us/op
[info] p( 0.0000) = 14.608 us/op
[info] p(50.0000) = 18.304 us/op
[info] p(90.0000) = 22.816 us/op
[info] p(95.0000) = 26.976 us/op
[info] p(99.0000) = 41.647 us/op
[info] p(99.9000) = 71.808 us/op
[info] p(99.9900) = 139.696 us/op
[info] p(99.9990) = 33048.112 us/op
[info] p(99.9999) = 1461714.944 us/op
[info] max = 1461714.944 us/op
[info] Benchmark Mode Cnt Score Error Units
[info] StashCreationBenchmark.testCustom sample 323534 27.607 ± 7.924 us/op
[info] StashCreationBenchmark.testDefault sample 356626 26.465 ± 15.980 us/op
AFTER:
[info] Result "testCustom":
[info] 22.710 ±(99.9%) 1.384 us/op [Average]
[info] (min, avg, max) = (15.168, 22.710, 110886.912), stdev = 233.744
[info] CI (99.9%): [21.326, 24.094] (assumes normal distribution)
[info] Samples, N = 308896
[info] mean = 22.710 ±(99.9%) 1.384 us/op
[info] min = 15.168 us/op
[info] p( 0.0000) = 15.168 us/op
[info] p(50.0000) = 19.776 us/op
[info] p(90.0000) = 28.608 us/op
[info] p(95.0000) = 33.344 us/op
[info] p(99.0000) = 49.216 us/op
[info] p(99.9000) = 90.253 us/op
[info] p(99.9900) = 594.334 us/op
[info] p(99.9990) = 8350.329 us/op
[info] p(99.9999) = 110886.912 us/op
[info] max = 110886.912 us/op
[info] Result "testDefault":
[info] 19.099 ±(99.9%) 0.424 us/op [Average]
[info] (min, avg, max) = (13.120, 19.099, 45940.736), stdev = 77.524
[info] CI (99.9%): [18.675, 19.523] (assumes normal distribution)
[info] Samples, N = 361741
[info] mean = 19.099 ±(99.9%) 0.424 us/op
[info] min = 13.120 us/op
[info] p( 0.0000) = 13.120 us/op
[info] p(50.0000) = 16.368 us/op
[info] p(90.0000) = 24.250 us/op
[info] p(95.0000) = 31.232 us/op
[info] p(99.0000) = 55.680 us/op
[info] p(99.9000) = 121.249 us/op
[info] p(99.9900) = 402.386 us/op
[info] p(99.9990) = 1767.264 us/op
[info] p(99.9999) = 45940.736 us/op
[info] max = 45940.736 us/op
[info]
[info]
[info] # Run complete. Total time: 00:02:01
[info]
[info] Benchmark Mode Cnt Score Error Units
[info] StashCreationBenchmark.testCustom sample 308896 22.710 ± 1.384 us/op
[info] StashCreationBenchmark.testDefault sample 361741 19.099 ± 0.424 us/op
This commit is contained in:
parent
18a24c0e50
commit
1b1ef752fe
3 changed files with 103 additions and 10 deletions
|
|
@ -123,14 +123,8 @@ private[akka] trait StashSupport {
|
|||
|
||||
/* The capacity of the stash. Configured in the actor's mailbox or dispatcher config.
|
||||
*/
|
||||
private val capacity: Int = {
|
||||
val dispatcher = context.system.settings.config.getConfig(context.props.dispatcher)
|
||||
val fallback = dispatcher.withFallback(context.system.settings.config.getConfig(Mailboxes.DefaultMailboxId))
|
||||
val config =
|
||||
if (context.props.mailbox == Mailboxes.DefaultMailboxId) fallback
|
||||
else context.system.settings.config.getConfig(context.props.mailbox).withFallback(fallback)
|
||||
config.getInt("stash-capacity")
|
||||
}
|
||||
private val capacity: Int =
|
||||
context.system.mailboxes.stashCapacity(context.props.dispatcher, context.props.mailbox)
|
||||
|
||||
/**
|
||||
* INTERNAL API.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package akka.dispatch
|
|||
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
import akka.ConfigurationException
|
||||
import akka.actor.{ Actor, ActorRef, ActorSystem, DeadLetter, Deploy, DynamicAccess, Props }
|
||||
import akka.dispatch.sysmsg.{ EarliestFirstSystemMessageList, LatestFirstSystemMessageList, SystemMessage, SystemMessageList }
|
||||
|
|
@ -14,8 +13,9 @@ import akka.event.EventStream
|
|||
import akka.event.Logging.Warning
|
||||
import akka.util.Reflect
|
||||
import com.typesafe.config.{ Config, ConfigFactory }
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import scala.annotation.tailrec
|
||||
|
||||
object Mailboxes {
|
||||
final val DefaultMailboxId = "akka.actor.default-mailbox"
|
||||
|
|
@ -232,4 +232,42 @@ private[akka] class Mailboxes(
|
|||
.withFallback(settings.config.getConfig(id))
|
||||
.withFallback(defaultMailboxConfig)
|
||||
}
|
||||
|
||||
private val stashCapacityCache = new AtomicReference[Map[String, Int]](Map.empty[String, Int])
|
||||
private val defaultStashCapacity: Int =
|
||||
stashCapacityFromConfig(Dispatchers.DefaultDispatcherId, Mailboxes.DefaultMailboxId)
|
||||
|
||||
/**
|
||||
* INTERNAL API: The capacity of the stash. Configured in the actor's mailbox or dispatcher config.
|
||||
*/
|
||||
private[akka] final def stashCapacity(dispatcher: String, mailbox: String): Int = {
|
||||
|
||||
@tailrec def updateCache(cache: Map[String, Int], key: String, value: Int): Boolean = {
|
||||
stashCapacityCache.compareAndSet(cache, cache.updated(key, value)) ||
|
||||
updateCache(stashCapacityCache.get, key, value) // recursive, try again
|
||||
}
|
||||
|
||||
if (dispatcher == Dispatchers.DefaultDispatcherId && mailbox == Mailboxes.DefaultMailboxId)
|
||||
defaultStashCapacity
|
||||
else {
|
||||
val cache = stashCapacityCache.get
|
||||
val key = dispatcher + "-" + mailbox
|
||||
cache.get(key) match {
|
||||
case Some(value) ⇒ value
|
||||
case None ⇒
|
||||
val value = stashCapacityFromConfig(dispatcher, mailbox)
|
||||
updateCache(cache, key, value)
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def stashCapacityFromConfig(dispatcher: String, mailbox: String): Int = {
|
||||
val disp = settings.config.getConfig(dispatcher)
|
||||
val fallback = disp.withFallback(settings.config.getConfig(Mailboxes.DefaultMailboxId))
|
||||
val config =
|
||||
if (mailbox == Mailboxes.DefaultMailboxId) fallback
|
||||
else settings.config.getConfig(mailbox).withFallback(fallback)
|
||||
config.getInt("stash-capacity")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright (C) 2015 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.actor
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import akka.testkit.TestProbe
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.openjdk.jmh.annotations._
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object StashCreationBenchmark {
|
||||
class StashingActor extends Actor with Stash {
|
||||
def receive = {
|
||||
case msg => sender() ! msg
|
||||
}
|
||||
}
|
||||
|
||||
val props = Props[StashingActor]
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Array(Mode.SampleTime))
|
||||
@Fork(3)
|
||||
@Warmup(iterations = 5)
|
||||
@Measurement(iterations = 10)
|
||||
class StashCreationBenchmark {
|
||||
val conf = ConfigFactory.parseString("""
|
||||
my-dispatcher = {
|
||||
stash-capacity = 1000
|
||||
}
|
||||
""")
|
||||
implicit val system: ActorSystem = ActorSystem("StashCreationBenchmark", conf)
|
||||
val probe = TestProbe()
|
||||
|
||||
@TearDown(Level.Trial)
|
||||
def shutdown() {
|
||||
system.terminate()
|
||||
Await.ready(system.whenTerminated, 15.seconds)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
def testDefault: Boolean = {
|
||||
val stash = system.actorOf(StashCreationBenchmark.props)
|
||||
stash.tell("hello", probe.ref)
|
||||
probe.expectMsg("hello")
|
||||
true
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
def testCustom: Boolean = {
|
||||
val stash = system.actorOf(StashCreationBenchmark.props.withDispatcher("my-dispatcher"))
|
||||
stash.tell("hello", probe.ref)
|
||||
probe.expectMsg("hello")
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue