sbt / sbt-jmh

"Trust no one, bench everything." - sbt plugin for JMH (Java Microbenchmark Harness)
Apache License 2.0
787 stars 91 forks source link

Validate jvmOpts are passed to forked JVMs properly #33

Open retronym opened 9 years ago

retronym commented 9 years ago

This might be something dumb in my environment, but it might also be a mistake in the 0.1,4 release.

:confused:

> jmh:version
[info] 0.9
> consoleProject
[info] Starting scala interpreter...
[info]
import sbt._
import Keys._
import dsl._
import _root_.org.sbtidea.SbtIdeaPlugin._
import _root_.net.virtualvoid.sbt.graph.Plugin._
import _root_.com.typesafe.sbteclipse.plugin.EclipsePlugin._
import _root_.pl.project13.scala.sbt.SbtJmh._
import _root_.sbt.plugins.IvyPlugin
import _root_.sbt.plugins.JvmPlugin
import _root_.sbt.plugins.CorePlugin
import _root_.sbt.plugins.JUnitXmlReportPlugin
import currentState._
import extracted._
import cpHelpers._
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> pl.project13.scala.sbt.SbtJmh.getClass.getProtectionDomain
res0: java.security.ProtectionDomain =
ProtectionDomain  (file:/Users/jason/.ivy2/cache/scala_2.10/sbt_0.13/pl.project13.scala/sbt-jmh/jars/sbt-jmh-0.1.4.jar <no signer certificates>)
 sbt.PluginManagement$PluginClassLoader@3fc2a1d1
 <no principals>
 java.security.Permissions@130f7c25 (
 ("java.util.PropertyPermission" "java.specification.version" "read")
 ("java.util.PropertyPermission" "java.version" "read")
 ("java.util.PropertyPermission" "os.arch" "read")
 ("java.util.PropertyPermission" "java.specification.vendor" "read")
 ("java.util.PropertyPermission" "java.vm.specification.name" "read")
 ("java.util.PropertyPermission" "java.vm.vendor" "read")
 ("java.util.PropertyPermission" "path.separator" "read")
 ("java.util.PropertyPermission" "os.version" "read")
 ("java.util.PropertyP...
scala> pl.project13.scala.sbt.SbtJmh.jmhSettings.find(_.toString.contains("version")).get.init.evaluate(null)
res1: Any = 0.9
retronym commented 9 years ago

Do'h, I meant to use 0.1.14, not 0.1.4.

ktoso commented 9 years ago

:smile: Yup, you want 0.1.14 :-)

// Thanks for the nice report though, if it was a bug that would have been very helpful :-)

retronym commented 9 years ago

I blame my fat-fingered-ness on the circles I'm circling trying to plug https://github.com/biboudis/jmh-profilers into my profiles.

Using the pre-built binary as instructed in the README, I'm unable to get past the "Please unlock commercial features" nag, even though I passed -XX:+UnlockCommercialFeatures to the SBT jvm and to the sbt-jmh jvmArgs.

I rebuilt that locally, but then needed to update it some API changes in JMH. But then the generated code still fails to compile with:

[error] }
[info] Benchmark entry {'scala.tools.nsc.JavacBenchmark.bench', Throughput, {}} already exists, overwriting
[error] (jmh:compile) javac returned nonzero exit code

But the javac error messages are swallowed.

So I'm building sbt-jmh locally to see if I can get those displayed...

ktoso commented 9 years ago

JMH itself forks JVMs, that's probably the problem - not sure if we're properly passing jvm options to those - probably not. I can look into these things a bit later today, need to look at conductr things now. Let me know if you find anything more so I can continue from where you get to in my evening perhaps.

(Reopened and renamed, I hope the title makes sense :-))

retronym commented 9 years ago

At the top of my problem stack, I think the problem with jmh:compile failing when the jmh-profilers plugin is on the classpath is related to duplicate classes being created.

I set a breakpoint in the spot in SBT where javac is called, and then reconstructed the command line:

// args.txt
-d
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes
-classpath
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes:/Users/jason/.ivy2/cache/org.scala-lang/scala-compiler/jars/scala-compiler-2.11.6.jar:/Users/jason/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.11.6.jar:/Users/jason/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.11.6.jar:/Users/jason/.ivy2/cache/org.scala-lang.modules/scala-xml_2.11/bundles/scala-xml_2.11-1.0.3.jar:/Users/jason/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.11/bundles/scala-parser-combinators_2.11-1.0.3.jar:/Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-core/jars/jmh-core-1.8.jar:/Users/jason/.ivy2/cache/net.sf.jopt-simple/jopt-simple/jars/jopt-simple-4.6.jar:/Users/jason/.ivy2/cache/org.apache.commons/commons-math3/jars/commons-math3-3.2.jar:/Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-generator-bytecode/jars/jmh-generator-bytecode-1.8.jar:/Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-generator-reflection/jars/jmh-generator-reflection-1.8.jar:/Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-generator-asm/jars/jmh-generator-asm-1.8.jar:/Users/jason/.ivy2/cache/org.ow2.asm/asm/jars/asm-5.0.3.jar:/Users/jason/.m2/repository/com/github/biboudis/jmh-profilers/0.1.3-SNAPSHOT/jmh-profilers-0.1.3-SNAPSHOT.jar:/Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-generator-annprocess/jars/jmh-generator-annprocess-1.8.jar:/Users/jason/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.11.6.jar
/Users/jason/code/scala-jmh-suite/src/main/scala/scala/tools/nsc/JavacBenchmark.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/infra/generated/Blackhole_jmh.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/infra/generated/Blackhole_jmh_B1.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/infra/generated/Blackhole_jmh_B2.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/infra/generated/Blackhole_jmh_B3.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/samples/generated/JMHSample_01_HelloWorld_jmh.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/samples/generated/JMHSample_01_HelloWorld_jmh_B1.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/samples/generated/JMHSample_01_HelloWorld_jmh_B2.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/samples/generated/JMHSample_01_HelloWorld_jmh_B3.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/org/openjdk/jmh/samples/generated/JMHSample_01_HelloWorld_wellHelloThere.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/CompilerBenchmark_compile.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/CompilerBenchmark_jmh.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/CompilerBenchmark_jmh_B1.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/CompilerBenchmark_jmh_B2.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/CompilerBenchmark_jmh_B3.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/JavacBenchmark_bench.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/JavacBenchmark_jmh.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/JavacBenchmark_jmh_B1.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/JavacBenchmark_jmh_B2.java
/Users/jason/code/scala-jmh-suite/target/scala-2.11/generated-sources/jmh/scala/tools/nsc/generated/JavacBenchmark_jmh_B3.java
javac @args.txt
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/org/openjdk/jmh/infra/generated/Blackhole_jmh_B1.java:3: error: duplicate class: org.openjdk.jmh.infra.generated.Blackhole_jmh_B1
public class Blackhole_jmh_B1 extends org.openjdk.jmh.infra.Blackhole {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/org/openjdk/jmh/infra/generated/Blackhole_jmh_B2.java:3: error: duplicate class: org.openjdk.jmh.infra.generated.Blackhole_jmh_B2
public class Blackhole_jmh_B2 extends Blackhole_jmh_B1 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/org/openjdk/jmh/infra/generated/Blackhole_jmh_B3.java:2: error: duplicate class: org.openjdk.jmh.infra.generated.Blackhole_jmh_B3
public class Blackhole_jmh_B3 extends Blackhole_jmh_B2 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/org/openjdk/jmh/infra/generated/Blackhole_jmh.java:2: error: duplicate class: org.openjdk.jmh.infra.generated.Blackhole_jmh
public class Blackhole_jmh extends Blackhole_jmh_B3 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/scala/tools/nsc/generated/JavacBenchmark_jmh_B1.java:3: error: duplicate class: scala.tools.nsc.generated.JavacBenchmark_jmh_B1
public class JavacBenchmark_jmh_B1 extends scala.tools.nsc.JavacBenchmark {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/scala/tools/nsc/generated/JavacBenchmark_jmh_B2.java:3: error: duplicate class: scala.tools.nsc.generated.JavacBenchmark_jmh_B2
public class JavacBenchmark_jmh_B2 extends JavacBenchmark_jmh_B1 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/scala/tools/nsc/generated/JavacBenchmark_jmh_B3.java:2: error: duplicate class: scala.tools.nsc.generated.JavacBenchmark_jmh_B3
public class JavacBenchmark_jmh_B3 extends JavacBenchmark_jmh_B2 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/scala/tools/nsc/generated/JavacBenchmark_jmh.java:2: error: duplicate class: scala.tools.nsc.generated.JavacBenchmark_jmh
public class JavacBenchmark_jmh extends JavacBenchmark_jmh_B3 {
       ^
/Users/jason/code/scala-jmh-suite/target/scala-2.11/classes/scala/tools/nsc/generated/JavacBenchmark_bench.java:34: error: duplicate class: scala.tools.nsc.generated.JavacBenchmark_bench
public final class JavacBenchmark_bench {
             ^
Note: Benchmark entry {'scala.tools.nsc.JavacBenchmark.bench', Throughput, {}} already exists, overwriting
9 errors

Removing /Users/jason/.ivy2/cache/org.openjdk.jmh/jmh-generator-annprocess/jars/jmh-generator-annprocess-1.8.jar from the classpath corrects this error.

sbt-jmh could guard against this mistake by adding the compiler option -proc:none (http://stackoverflow.com/questions/882295/maven-compilation-error-duplicate-classes)

I was able to workaround this with:

libraryDependencies += "com.github.biboudis" % "jmh-profilers" % "0.1.3-SNAPSHOT" intransitive()
retronym commented 9 years ago

I was then able to gather the profiling data with:

 run -jvmArgsPrepend -XX:+UnlockCommercialFeatures -i 1 -wi 1 -prof jfr
ktoso commented 9 years ago

Awesome detective work, thanks a lot @retronym! I'll incorporate those hints and spin a release soon :-)

retronym commented 9 years ago

I still can't get this working with the binary release of jmh-profilers. There seems to be a forked VM running its code without -XX:+UnlockCommercialFeatures. About to add some diagnostics to a locally built copy to find that..

retronym commented 9 years ago

> set javaOptions in run += "-XX:+UnlockCommercialFeatures" does the trick.

retronym commented 9 years ago

See: https://github.com/biboudis/jmh-profilers/pull/4 for the last problem on the stack :smile:

ktoso commented 9 years ago

Great to see that project is active :-)