+tes introduce simple way to gather flamegraphs from multinode specs

This commit is contained in:
Konrad Malawski 2016-06-24 11:21:21 +02:00
parent b6a94e1758
commit 7c79b40dea
3 changed files with 70 additions and 5 deletions

View file

@ -5,15 +5,18 @@ package akka.remote.testkit
import language.implicitConversions
import java.net.{ InetAddress, InetSocketAddress }
import com.typesafe.config.{ ConfigObject, ConfigFactory, Config }
import scala.concurrent.{ Await, Awaitable }
import com.typesafe.config.{ Config, ConfigFactory, ConfigObject }
import scala.concurrent.{ Await, Awaitable, Future }
import scala.util.control.NonFatal
import scala.collection.immutable
import akka.actor._
import akka.util.Timeout
import akka.remote.testconductor.{ TestConductorExt, TestConductor, RoleName }
import akka.remote.testconductor.{ RoleName, TestConductor, TestConductorExt }
import akka.testkit._
import akka.testkit.TestEvent._
import scala.concurrent.duration._
import akka.remote.testconductor.RoleName
import akka.actor.RootActorPath

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2016 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.remote.testkit
import java.io.File
import akka.remote.testconductor.RoleName
import scala.concurrent.Future
import scala.concurrent.duration._
/**
* INTERNAL API: Support trait allowing trivially recording perf metrics from [[MultiNodeSpec]]s
*/
private[akka] trait PerfFlamesSupport { _: MultiNodeSpec
/**
* Runs `perf-java-flames` script on given node (JVM process).
* Refer to https://github.com/jrudolph/perf-map-agent for options and manual.
*
* Options are currently to be passed in via `export PERF_MAP_OPTIONS` etc.
*/
def runPerfFlames(nodes: RoleName*)(delay: FiniteDuration, time: FiniteDuration = 15.seconds): Unit = {
if (isPerfJavaFlamesAvailable && isNode(nodes: _*)) {
import scala.concurrent.ExecutionContext.Implicits.global
val afterDelay = akka.pattern.after(delay, system.scheduler)(Future.successful("GO!"))
afterDelay onComplete { it
import java.lang.management._
val name = ManagementFactory.getRuntimeMXBean.getName
val pid = name.substring(0, name.indexOf('@')).toInt
val perfCommand = s"$perfJavaFlamesPath $pid"
println(s"[perf @ $myself($pid)][OUT]: " + perfCommand)
import scala.sys.process._
perfCommand.run(new ProcessLogger {
override def buffer[T](f: T): T = f
override def out(s: String): Unit = println(s"[perf @ $myself($pid)][OUT] " + s)
override def err(s: String): Unit = println(s"[perf @ $myself($pid)][ERR] " + s)
})
}
}
}
def perfJavaFlamesPath: String =
"/home/ubuntu/perf-java-flames"
def isPerfJavaFlamesAvailable: Boolean = {
val isIt = new File(perfJavaFlamesPath).exists()
if (!isIt) println(s"WARN: perf-java-flames not available under [$perfJavaFlamesPath]! Skipping perf profiling.")
isIt
}
}

View file

@ -6,13 +6,14 @@ package akka.remote.artery
import java.nio.ByteBuffer
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit.NANOSECONDS
import scala.concurrent.duration._
import scala.concurrent.duration._
import akka.actor._
import akka.remote.RemoteActorRefProvider
import akka.remote.testconductor.RoleName
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.remote.testkit.PerfFlamesSupport
import akka.remote.testkit.STMultiNodeSpec
import akka.serialization.ByteBufferSerializer
import akka.serialization.SerializerWithStringManifest
@ -199,7 +200,8 @@ class MaxThroughputSpecMultiJvmNode2 extends MaxThroughputSpec
abstract class MaxThroughputSpec
extends MultiNodeSpec(MaxThroughputSpec)
with STMultiNodeSpec with ImplicitSender {
with STMultiNodeSpec with ImplicitSender
with PerfFlamesSupport {
import MaxThroughputSpec._
@ -269,6 +271,8 @@ abstract class MaxThroughputSpec
import testSettings._
val receiverName = testName + "-rcv"
runPerfFlames(first, second)(delay = 5.seconds, time = 15.seconds)
runOn(second) {
val rep = reporter(testName)
for (n 1 to senderReceiverPairs) {