Open vyazelenko opened 7 years ago
It seems to be a problem with all 0.4.x
releases.
this means there is no jmh plugin that works with gradle 4.0
I suspect the manifest entry is missing, but you can still execute the benchmark using
java -cp ... org.openjdk.jmh.Main
On a side note, I don't think the plugin should generate a jar with dependencies included, this is a packaging issue that is solved by the shadow plugin. So technically speaking, the plugin is right: the jar should NOT include a manifest entry with org.openjdk.jmh.Main
as main class, because it's found in the JMH jar.
Why don't use use the jmh
task to run the benchmarks? If you want to run it from CLI, then you need to put the generated jar on classpath, plus JMH dependencies.
its good practice to run the jar file standalone because then there are less processes interfering with the benchmark. also the readme file says that the dependencies are included. I really don't care how i build my jar, if the shadow plugin is the way to go, thats fine too, maybe put an example how to do it into the readme.
Ok so to sum up:
its good practice to run the jar file standalone because then there are less processes interfering with the benchmark.
Yes, however the task is often enough. I get the point.
the readme file says that the dependencies are included
The readme is wrong :), let's fix it
I really don't care how i build my jar, if the shadow plugin is the way to go, thats fine too, maybe put an example how to do it into the readme.
I wouldn't say it's the way to go. Personally I wouldn't use it. However, I agree that:
shadow
plugin in the README would be niceAnd finally, do we agree that we don't have to create a fat jar?
ok i agree with all your points. if its possible to create the jar file with or without deps that's great. Its just a matter of documentation really.
I see that the readme file already documents how to use the shadow plugin. one thing that I'm not sure about is how the shadow task is called. jmhShadowJar maybe?
the shadow task is called internally. If the shadow
plugin is explicitly added to the build then the fat jar is created using a task of type ShadowJar
, otherwise the standard Jar
type is used. This usage is transparent to the user thus there's no jmhShadowJar
task leaking to the build itself, it's just jmhJar
.
@aalmiray how does it know that I want to use the shadow plugin for my JMH jar and not for my normal app jar file?
With: Gradle 3.5.1, JMH Plugin 0.2.0 Fat Jar created, with all required dependencies. I run ./gradlew :generic-benchmarks:jmh and everything works as expected. :+1:
With Gradle 4.0.1, JMH Plugin 0.4.x Jar only includes benchmark code. I run ./gradlew :generic-benchmarks:jmh and it fails with a java.lang.NoClassDefFoundError, since this is a multi module project the perticular classes that are missing are project dependencies (I assume this would also occur with 3rd party deps) :-1:
This is a problem for me and I hope you not going to say I should be including all my project deps in the jmh configuration. Never had to before. /cc @melix
Same problem as what @juddgaddie has mentioned around missing project dependencies
This issue was unexpectedly resolved for me when switching includeTests from false to true. jmh { includeTests = true }
The dependencies are compile not compileTest so have no idea why this should resolve the issue.
Maybe this will help... I recently upgraded a project to Gradle >= 4.2 from 3.2.x as a part of a migration toward JDK9. I had to use plugin 0.4.5-beta-2 to resolve the lock issue on the Windows platform, which meant I ended up with Gradle 4.3.1.
As a part of the Gradle upgrade, I switched from the older java
plugin to the new java-library
plugin. I don't know how support of the old java
plugin works in Gradle 4.x, but if it's basically "adapting" to the newer conventions then this may still apply.
Everything pretty much worked, except I had to slightly tweak my dependencies to add:
dependencies {
// ...
jmh configurations.api
}
Gradle now separates api
dependencies from implementation
dependencies, and I was getting compile errors from the benchmark classes on unknown packages/classes from one of my api
-declared dependencies.
Same problem here with 0.4.5. Resulting benchmarks jar is not a shadow jar -- dependencies are included inside as jars, so it cannot run with java -jar benchmarks.jar
. Using -cp
and specifying main class does not help (it is not there). Any update on this issue?
Finally worked for me. Here is the workaround.
jmh-gradle-plugin
whould only generate shadowjar if that plugin is present in your project (otherwise it generates jar with dependencies simply packed as jars inside):buildscript {
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:2.0.2"
}
}
apply plugin: "com.github.johnrengelman.shadow"
compile
dependencies or it is not going to be included into the resulting shadowjar:buildscript {
ext.jmh_version = '1.20'
}
jmh {
jmhVersion = jmh_version
}
dependencies {
compile "org.openjdk.jmh:jmh-core:$jmh_version"
}
I also have not yet found a working combination of this plugin with Gradle 4 and Java 8.
With ./gradlew jmh
I get "error reading benchmark list" due to some odd zip error.
With jmhJar
I get a fat jars that contain the dependencies as jar files inside the jar, rather than a proper shadow jar with unpacked contents, despite having the shadow plugin loaded. If I unpack this jar, build the classpath manually, then it will run.
So I am now also using the "workaround" by @elizarov - because it works:
plugins { // ...
// id 'me.champeau.gradle.jmh' version '0.4.5' // did not work
id 'com.github.johnrengelman.shadow' version '2.0.2'
}
shadowJar {
destinationDir = project.rootDir
archiveName = 'benchmarks.jar'
classifier = 'benchmarks'
manifest.attributes('Main-Class': 'org.openjdk.jmh.Main')
}
compile
or compileOnly
(annotation processor) dependencies.
buildscript {
ext.jmh_version = '1.20' // JMH version to use
}
dependencies {
compile group: 'org.openjdk.jmh', name: 'jmh-core', version: jmh_version
compileOnly group: 'org.openjdk.jmh', name: 'jmh-generator-annprocess', version: jmh_version
}
./gradlew shadowJar
, then run the jar.Works fine without the plugin, with minimal effort; at least for basic setups like mine.
"error reading benchmark list" - this might be caused by a running gradle daemon still having the JAR opened. When rebuilding the jar it sometimes won't be reopened and causes strange Zip reading errors.
The workarounds above didn't work for me on gradle 5.4.1, so this is what is working for me:
plugins {
id("me.champeau.gradle.jmh") version "0.4.8"
id("com.github.johnrengelman.shadow") version "5.0.0"
}
...
// jmhJar task provided by jmh gradle plugin is currently broken
// https://github.com/melix/jmh-gradle-plugin/issues/97
// so instead, we configure the shadowJar task to have JMH bits in it
tasks.shadowJar {
manifest {
attributes(Pair("Main-Class", "org.openjdk.jmh.Main"))
}
// include dependencies
configurations.add(project.configurations.jmh.get())
// include benchmark classes
from(project.sourceSets.jmh.get().output)
// include generated java source, BenchmarkList and other JMH resources
from(tasks.jmhRunBytecodeGenerator.get().outputs)
// include compiled generated classes
from(tasks.jmhCompileGeneratedClasses.get().outputs)
dependsOn(tasks.jmhCompileGeneratedClasses)
}
@marshallpierce can you please provide us a full example ?
I have the same problem with error :
Could not find method get() for arguments[] on configuration ':jmh' of type org.gradle.api.internal.artifacts.configurations.DefaultConfiguration
This is what is working for me with: `./gradlew -version
Build time: 2019-04-26 08:14:42 UTC Revision: 261d171646b36a6a28d5a19a69676cd098a4c19d
Kotlin: 1.3.21 Groovy: 2.5.4 Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018 JVM: 12.0.1 (Oracle Corporation 12.0.1+12) OS: Mac OS X 10.14.4 x86_64`
And my build.gradle file : `/*
plugins { id 'java' id 'me.champeau.gradle.jmh' version '0.4.8' }
repositories { mavenLocal() maven { url = 'http://repo.maven.apache.org/maven2' } jcenter() }
dependencies { (...) compile 'org.openjdk.jmh:jmh-core:1.21' jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.21' }
sourceCompatibility = '1.8'
sourceSets { main.java.srcDirs = ['src/main/java', 'src/jmh/java'] }
tasks.getByName('jmhJar').doFirst() {duplicatesStrategy(DuplicatesStrategy.EXCLUDE)}
jmh { iterations = 10 fork = 5 jvmArgs = '-server' timeUnit = 's' warmupIterations =5 jmhVersion = '1.21' benchmarkMode = ['avgt'] duplicateClassesStrategy = 'exclude' } `
You can see my work here porting roaring bitmap's build to gradle: https://github.com/RoaringBitmap/RoaringBitmap/pull/343
Latest version of the plugin
0.4.2
generates incomplete jar: the jar files only contains project code and no third-party dependencies. In fact it is much weirded as it includes project classes with 3rd party dependencies as jars and no JMH classes or jars./cc @aalmiray @melix