Does YourKit report ReentrantLocks?

Questions about YourKit Java Profiler
Post Reply
binil
Posts: 5
Joined: Fri Mar 26, 2010 10:58 pm

Does YourKit report ReentrantLocks?

Post by binil »

I am using YourKit 8.0.24 on Solaris 10 with Sun 1.6u18 32-bit JVM.

I am trying to reduce the lock contention on a particular code-path in my application. To identify code with high lock contention, I connect YourKit to my application and use the "Monitor" tab and see acquiring which locks have caused the thread I care about to block. My eventual aim is to have no red dots for this thread in the "Thread" tab in YK GUI.

Often the contention arises from read/read locking using an intrinsic lock, so those can be improved by using a ReentrantLock instead of the intrinsic lock. Indeed when I tried this, YourKit reported lower contention. Is that information reliable? Does YourKit report usage of ReentrantLock's correctly?

(crossposted at http://stackoverflow.com/questions/3045 ... trantlocks)
binil
Posts: 5
Joined: Fri Mar 26, 2010 10:58 pm

Re: Does YourKit report ReentrantLocks?

Post by binil »

Looks like ReentrantLocks are reported as "waiting" instead of "blocked". I wrote a test program where a lock is contended by two threads. When the lock is intrinsic, YJP correctly identifies when threads are blocked:
Image

But when I use the write lock of a ReentrantReadWriteLock, YJP identifies the thread as waiting instead of blocked:
Image

Notice that although my previous post describes using Sun JVM on Solaris, I ran this test on my Mac OS X 10.5 desktop using 1.6 64-bit JVM and YourKit 8.0.24.

Is this a bug or expected behavior? I would like ReentrantLocks also to be listed in the monitor profile.

Here is my program:

Code: Select all

package lock.yjp.test;

import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class YjpLockTest {

	private static class State {
		private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);

		public void contended(boolean intrinsic) {
			if (intrinsic) {
				longTaskWithIntrinsicLocking();
			} else {
				longTaskWithExtrinsicLocking();
			}
		}

		private synchronized void longTaskWithIntrinsicLocking() {
			longTask("intrinsic");
		}

		private void longTaskWithExtrinsicLocking() {
			lock.writeLock().lock();
			try {
				longTask("extrinsic");
			} finally {
				lock.writeLock().unlock();
			}
		}

		private void longTask(String type) {
			try {
				System.out.println("[" + type + "] Thread " + Thread.currentThread().getName() 
                                + " doing long computation");
				// simulating long computation holding a lock with sleep :-)
				Thread.sleep(random.nextInt(10) * 1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private static class MyRunnable implements Runnable {
		private final boolean intrinsic;

		private volatile boolean running = false;

		public MyRunnable(boolean intrinsic) {
			this.intrinsic = intrinsic;
		}

		@Override
		public void run() {
			System.out.println("Starting thread " + Thread.currentThread().getName());
			running = true;
			while (running) {
				shared.contended(intrinsic);
				try {
					Thread.sleep(random.nextInt(10) * 100L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println("Ending thread " + Thread.currentThread().getName());
		}

		public void stop() {
			running = false;
		}
	}

	private static final Random random = new Random();
	private static final State shared = new State();

	public static void main(String[] args) {
		boolean intrinsic = false;

		System.out.println("Starting");
		MyRunnable run1 = new MyRunnable(intrinsic);
		MyRunnable run2 = new MyRunnable(intrinsic);


		new Thread(run1, "MyThread 1").start();
		new Thread(run2, "MyThread 2").start();
		try {
			Thread.sleep(5*60*1000L);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			run1.stop();
			run2.stop();
		}

		System.out.println("Done");
	}
}
Anton Katilin
Posts: 6172
Joined: Wed Aug 11, 2004 8:37 am

Re: Does YourKit report ReentrantLocks?

Post by Anton Katilin »

Hello,

The thread states are shown exactly as they are reported by JVM. In particular, JVM shows "waiting" for the methods in your example.

As a workaround, there could be a list of methods for which status should be shown as "blocked" even if reported by JVM as "waiting", to better reflect their semantics.
I would like ReentrantLocks also to be listed in the monitor profile.
The Monitors feature uses JVM API which handles only Java synchronization primitives. Unfortunately, JVM does not issue similar events for ReentrantLocks. As a workaround, you can measure wall time for all methods ( http://www.yourkit.com/docs/90/help/times.jsp ) and use CPU profiling to see if the lock methods are in the hot spots.

Best regards,
Anton
binil
Posts: 5
Joined: Fri Mar 26, 2010 10:58 pm

Re: Does YourKit report ReentrantLocks?

Post by binil »

Anton,

Thanks for responding!
As a workaround, there could be a list of methods for which status should be shown as "blocked" even if reported by JVM as "waiting", to better reflect their semantics.
I would be very delighted if you could add that feature to YourKit! Or did you mean that it is possible currently?

The Monitors feature uses JVM API which handles only Java synchronization primitives. Unfortunately, JVM does not issue similar events for ReentrantLocks.
Again, it would be great if you folks can somehow get this to work. I am OK with using a patched JVM to get this feature.

BTW, love the product -- keep up the good work!
Anton Katilin
Posts: 6172
Joined: Wed Aug 11, 2004 8:37 am

Re: Does YourKit report ReentrantLocks?

Post by Anton Katilin »

Hello,

Thank you very much for your kind words.
As a workaround, there could be a list of methods for which status should be shown as "blocked" even if reported by JVM as "waiting", to better reflect their semantics.

I would be very delighted if you could add that feature to YourKit! Or did you mean that it is possible currently?
Not yet possible. A feature request for next version has been added.
Again, it would be great if you folks can somehow get this to work. I am OK with using a patched JVM to get this feature.
Unfortunately, we cannot change this. It's an essential part of JVM and we cannot affect it.

What we could do is to manually trace corresponding method calls. However, it seems to be quite similar to what you can get now by using CPU profiling. Measure all methods as wall time, and see if the synchronization methods are at the top.

Best regards,
Anton
Post Reply