diff --git a/build.sbt b/build.sbt index 9bc4176..f207002 100644 --- a/build.sbt +++ b/build.sbt @@ -77,7 +77,7 @@ lazy val jvm = addJmh(project).settings( lazy val addJavaOptions = javaOptions ++= { def refOf(version: String) = { - val HasSha = """.*(?:bin|pre)-([0-9a-f]{7,})(?:-.*)?""".r + val HasSha = """.*(?:bin|pre)-([0-9a-f]{7,})(?:-.*)?""".r version match { case HasSha(sha) => sha case _ => "v" + version @@ -100,5 +100,8 @@ def addJmh(project: Project): Project = { // IntelliJ SBT project import doesn't like sbt-jmh's default setup, which results the prod and test // output paths overlapping. This is because sbt-jmh declares the `jmh` config as extending `test`, but // configures `classDirectory in Jmh := classDirectory in Compile`. - project.enablePlugins(JmhPlugin).overrideConfigs(JmhConfig.extend(Compile)) + project.enablePlugins(JmhPlugin).overrideConfigs(JmhConfig.extend(Compile)).settings( + version in Jmh := "1.24" // duplicated in project/build.sbt + ) } + diff --git a/compilation/src/main/scala/scala/tools/nsc/ScalacBenchmark.scala b/compilation/src/main/scala/scala/tools/nsc/ScalacBenchmark.scala index cfb3dc0..ac673ca 100644 --- a/compilation/src/main/scala/scala/tools/nsc/ScalacBenchmark.scala +++ b/compilation/src/main/scala/scala/tools/nsc/ScalacBenchmark.scala @@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit import com.typesafe.config.ConfigFactory import org.openjdk.jmh.annotations.Mode._ import org.openjdk.jmh.annotations._ +import org.openjdk.jmh.profile.AsyncProfiler import scala.tools.benchmark.BenchmarkDriver @@ -22,6 +23,20 @@ trait BaseBenchmarkDriver { def compilerArgs: List[String] def sourceFiles: List[String] def isResident: Boolean = false + def compileProfiled(): Unit = { + val profiler: AsyncProfiler.JavaApi = try { + AsyncProfiler.JavaApi.getInstance() + } catch { + case _: LinkageError => null + } + if (profiler != null) profiler.filterThread(Thread.currentThread(), true) + try { + compileImpl() + } finally { + if (profiler != null) profiler.filterThread(Thread.currentThread(), false) + } + } + def compileImpl(): Unit } @State(Scope.Benchmark) @@ -123,7 +138,7 @@ object ScalacBenchmarkStandalone { @Fork(value = 16, jvmArgs = Array("-XX:CICompilerCount=2", "-Xms2G", "-Xmx2G", "-Xss2M")) class ColdScalacBenchmark extends ScalacBenchmark { @Benchmark - def compile(): Unit = compileImpl() + def compile(): Unit = compileProfiled() } @BenchmarkMode(Array(org.openjdk.jmh.annotations.Mode.SampleTime)) @@ -133,7 +148,7 @@ class ColdScalacBenchmark extends ScalacBenchmark { @Fork(value = 3, jvmArgs = Array("-Xms2G", "-Xmx2G", "-Xss2M")) class WarmScalacBenchmark extends ScalacBenchmark { @Benchmark - def compile(): Unit = compileImpl() + def compile(): Unit = compileProfiled() } @BenchmarkMode(Array(org.openjdk.jmh.annotations.Mode.SampleTime)) @@ -143,5 +158,5 @@ class WarmScalacBenchmark extends ScalacBenchmark { @Fork(value = 3, jvmArgs = Array("-Xms2G", "-Xmx2G", "-Xss2M")) class HotScalacBenchmark extends ScalacBenchmark { @Benchmark - def compile(): Unit = compileImpl() + def compile(): Unit = compileProfiled() } diff --git a/compilation/src/main/scalac/scala/tools/benchmark/BenchmarkDriver.scala b/compilation/src/main/scalac/scala/tools/benchmark/BenchmarkDriver.scala index c90a957..9b64a9e 100644 --- a/compilation/src/main/scalac/scala/tools/benchmark/BenchmarkDriver.scala +++ b/compilation/src/main/scalac/scala/tools/benchmark/BenchmarkDriver.scala @@ -4,6 +4,7 @@ import java.io.File import java.nio.file._ import com.typesafe.config.ConfigFactory +import org.openjdk.jmh.profile.AsyncProfiler import scala.tools.nsc._ diff --git a/infrastructure/src/main/java/scala/bench/ScalacBenchmarkRunner.java b/infrastructure/src/main/java/scala/bench/ScalacBenchmarkRunner.java index 31a9fdc..f9aea4d 100644 --- a/infrastructure/src/main/java/scala/bench/ScalacBenchmarkRunner.java +++ b/infrastructure/src/main/java/scala/bench/ScalacBenchmarkRunner.java @@ -72,6 +72,7 @@ public static Options setParameters(CommandLineOptions clOpts) throws IOExceptio } public static void main(String[] args) throws Exception { + System.out.println(java.util.Arrays.asList(args)); CommandLineOptions opts = new CommandLineOptions(args); // Support `-h/-l/lp/lprof/lrf`. if (opts.shouldHelp() || opts.shouldList() || opts.shouldListProfilers() || opts.shouldListResultFormats() || opts.shouldListWithParams()) { diff --git a/project/Profilers.scala b/project/Profilers.scala index 5bd6b77..2fd5542 100644 --- a/project/Profilers.scala +++ b/project/Profilers.scala @@ -10,7 +10,7 @@ abstract class Profiler(val name: String) { val flameGraphOpts = s"--minwidth,1,--colors,java,--cp,--width,1800" } object Profiler { - def all = List(basic, jfr, asyncAlloc, asyncCpu, perfNorm) + def all = List(basic, jfr, asyncAlloc, asyncCpu, asyncWall, perfNorm) def commands = Profiler.all.map { prof => Command.arb(profParser("prof" + prof.toString.capitalize))(commandImpl(List(prof))) } :+ Command.arb(profParser("prof"))(commandImpl(Profiler.all)) @@ -40,11 +40,12 @@ case object jfr extends Profiler("jfr") { sealed abstract class async(event: String) extends Profiler("async-" + event) { val framebuf = 33554432 def command(outDir: File): String = { - s"""-prof "jmh.extras.Async:dir=${outDir.getAbsolutePath};flameGraphOpts=$flameGraphOpts;verbose=true;event=$event;framebuf=${framebuf}" """ + s"""-prof "async:dir=${outDir.getAbsolutePath};libPath=${System.getenv("ASYNC_PROFILER_DIR")}/build/libasyncProfiler.so;minwidth=1;width=1800;verbose=true;event=$event;filter=${event == "wall"};flat=40;trace=10;framebuf=${framebuf};output=flamegraph,jfr,text" """ } // + ";simplename=true" TODO add this after upgrading next sbt-jmh release } case object asyncCpu extends async("cpu") case object asyncAlloc extends async("alloc") +case object asyncWall extends async("wall") case object perfNorm extends Profiler("perfNorm") { def command(outDir: File): String = "-prof perfnorm" } \ No newline at end of file diff --git a/project/build.sbt b/project/build.sbt index e69de29..642cbb8 100644 --- a/project/build.sbt +++ b/project/build.sbt @@ -0,0 +1,9 @@ +val jmhV = "1.24" // duplicated in build.sbt + +libraryDependencies ++= List( + "org.openjdk.jmh" % "jmh-core" % jmhV, + "org.openjdk.jmh" % "jmh-generator-bytecode" % jmhV, + "org.openjdk.jmh" % "jmh-generator-reflection" % jmhV +) + +resolvers in Global += Resolver.mavenLocal