melix / jmh-gradle-plugin

Integrates the JMH benchmarking framework with Gradle
Apache License 2.0
666 stars 88 forks source link

Sample project does not work out of the box. #118

Open AbuCarlo opened 6 years ago

AbuCarlo commented 6 years ago

I dutifully pulled the sample project for the plug-in, and get the same behavior I'd previously gotten, trying to integrate JMH into an existing project. Interesting, I then get this problem running in a Cygwin console:

$ gradle clean
Task :jmh Last added: null
:clean FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':clean'.
> Unable to delete file: C:\Users\antho\Code\jmh-gradle-example\build\libs\custom-1.0-SNAPSHOT-jmh.jar

JMH-fail.txt

sumin7928 commented 6 years ago

I'm in the same state, and then java process remain in windows system monitoring.

asarkar commented 6 years ago

This seems to be caused by the fact that Windows is not a real OS, more like a POS, and doesn't support daemon threads. Try launching Gradle with --no-daemon

sumin7928 commented 6 years ago

thanks, i solved to get using your Gradle option with --no-daemon

asarkar commented 6 years ago

@sumin7928 Happy to help. Use the close button.

spiffomatic64 commented 6 years ago

I think this has more to do with the fact that the worker is being launched with a generated file in its class path, I just tried this on a redhat system and while it "works", I think its works because linux is less complain-y about deleteing files that have active handles open.

After the jmh run, I ran a gradle clean and lsof shows this:

java      46621 49301      spiffomatic64   12r      REG              253,2  19037535  407360556 /home/spiffomatic64/test/develop/testProject/build/libs/testProject-1.0.0.21-jmh.jar (deleted)
java      46621 49305      spiffomatic64  DEL       REG              253,2            407360556 /home/spiffomatic64/test/develop/testProject/build/libs/testProject-1.0.0.21-jmh.jar
java      46621 49305      spiffomatic64   12r      REG              253,2  19037535  407360556 /home/spiffomatic64/test/develop/testProject/build/libs/testProject-1.0.0.21-jmh.jar (deleted)

Im pretty new to java/gradle/jmh, but after tinkering a bit I think its because of JMHTask.java:62 setting the classpath for the worker. And since GradleWorkerMain.java:60 loads the class before launching the ActionExecutionWorker, (by design) the CountDownLatch inside the worker is never tripped (I think it stays open waiting for additionally dispatched work).

I set breakpoints on the creation of the jmh.jar file handle and found it used in 2 places:

1)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at worker.org.gradle.internal.reflect.JavaMethod.findMethod(JavaMethod.java:57)
    at worker.org.gradle.internal.reflect.JavaMethod.findMethod(JavaMethod.java:59)
    at worker.org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:32)
    at worker.org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:36)
    at worker.org.gradle.internal.reflect.JavaReflectionUtil.method(JavaReflectionUtil.java:186)
    at worker.org.gradle.internal.classloader.ClassLoaderUtils.getMethodWithFallback(ClassLoaderUtils.java:59)
    at worker.org.gradle.internal.classloader.ClassLoaderUtils.<clinit>(ClassLoaderUtils.java:52)
    at worker.org.gradle.internal.classloader.FilteringClassLoader.<clinit>(FilteringClassLoader.java:48)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:57)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:67)

and 2)

    at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69)
    at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:94)
    at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122)
    at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:152)
    at java.net.URL.openStream(URL.java:1045)
    at org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:83)
    at org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:122)
    at org.openjdk.jmh.runner.Runner.internalRun(Runner.java:263)
    at org.openjdk.jmh.runner.Runner.run(Runner.java:209)
    at me.champeau.gradle.IsolatedRunner.run(IsolatedRunner.java:38)
    at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:36)
    at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:46)
    at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:100)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:748)

The 2nd is closed (or goes out of scope normally), the first stays put and a jstack of that threads after the jmh job is done shows:

"main" #1 prio=5 os_prio=0 tid=0x000000000522e000 nid=0x2a88 waiting on condition [0x000000000532f000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006c181d040> (a java.util.concurrent.CountDownLatch$Sync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
        at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
        at org.gradle.process.internal.worker.request.WorkerAction.execute(WorkerAction.java:68)
        at org.gradle.process.internal.worker.request.WorkerAction.execute(WorkerAction.java:36)
        at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:83)
        at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:35)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:119)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:64)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:62)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:67)

Again take all of this with a grain of salt as I'm not a java expert. Just wanted to chime in with what I found and point out that linux has the same issue windows does, linux is just more lax about letting you delete files in use.

I will add that using --no-daemon has resolved the issue on both linux and windows though :) thanks!