0

We use the Java ThreadPoolExecutor extensively. Specifically, we follow a fork join pattern, with building a list of callables and using the timed variant of invokeAll() on them. We only use these thread pools to perform I/O (non CPU intensive) operations, however looking at the thread dump, we see these specific threads consume high CPU. Looking at FutureTask.awaitDone() implementation, I can see that there is busy-wait strategy implemented with interleaved calls to LockSupport.parkNanos(). Looking at the JavaDoc for parkNanos itself, I see this comment "can return spuriously..", which makes me wonder if the awaitDone() is spinning and in turn causing high CPU. Any help will be appreciated!

lbalazscs
  • 17,474
  • 7
  • 42
  • 50
RPJ
  • 39
  • 3
  • Did you check the CPU activity with a profiler? – lbalazscs Oct 19 '15 at 17:44
  • I am weaving the outputs of jstack and top using this technique described here to find the threads in question. http://www.boxjar.com/using-top-and-jstack-to-find-the-java-thread-that-is-hogging-the-cpu/ – RPJ Oct 19 '15 at 17:51
  • A profiler gives much mode detailed information, not just which thread uses the CPU, but also which method. There are free java profilers, such as VisualVm and "Java Mission Control". – lbalazscs Oct 19 '15 at 17:59
  • The thread dump also gives you the stacktrace, which in turn gives you the method. – RPJ Oct 19 '15 at 18:01
  • In order to get real statistics, you should analyze many stacktraces - effectively doing manually what the profiler does automatically. Also this method seems to be error-prone. Anyway, I don't think that LockSupport.parkNanos consumes the CPU, but unless you provide a working example that reproduces the problem, is is hard to prove it. – lbalazscs Oct 19 '15 at 18:24
  • @lbalazscs I wasn't saying parkNanos consume CPU, I am just trying to explain why something that effectively just waits for I/O is consuming high CPU, I saw the invokeAll appearing consistently in my thread dumps and drilling down I found the busy-wait like implementation of futureTask.awaitDone, but as you said that may not be the issue. From experience, is there anything else you could think of/suggest? – RPJ Oct 19 '15 at 21:41
  • Be careful. Seeing a stacktrace showing a single method consuming lots of time, doesn’t imply that the time has been spent *on the same object* all the time. When you submit lots of jobs via `invokeAll`, you may see lots of `awaitDone()` calls consuming CPU time, not because they are spinning but because they all are eventually returning because each particular job has been done. You will need a more sophisticated analysis… – Holger Oct 20 '15 at 14:48

2 Answers2

0

I see this comment "can return spuriously.."

The same is true for a ReentrantLock and Condition#await. One of the reasons you usually associate an await or wait with a while loop is because of the spurious nature of thread suspension. That said, since we don't worry about the spurious wake up with a Condition you shouldn't worry about it here either.

It does do a spin but it's not busy. The first loop is usually quickly followed by a suspension.

John Vint
  • 39,695
  • 7
  • 78
  • 108
  • is it possible that park() 'mostly succeeds' in getting a permit, because there are let's say a lot of other concurrent unparking threads? – RPJ Oct 19 '15 at 19:45
  • Also, is it possible that a lot of wakeups happening for the fork thread causes high CPU? – RPJ Oct 19 '15 at 19:47
0

I think that awaitDone is not "busy-wait like" exactly because it calls parkNanos. parkNanos is conceptually similar to Object.wait(): a thread is waiting, but the CPU can other things in the meantime. The infinite loop is there because of the spurious wakeups, but these are an OS issue, and they also don't imply an active busy waiting.

The thread might be spending a lot of time in the method ("wall clock time"), but this is not necessarily CPU time. My recommendation is to use a profiler, because they can make this distinction, and they can help you find the real CPU bottleneck.

Related questions:

What specifically are wall-clock-time, user-cpu-time, and system-cpu-time in UNIX?

Unsafe.park vs Object.wait

How can I Monitor cpu usage per thread of a java application in a linux multiprocessor environment?

Community
  • 1
  • 1
lbalazscs
  • 17,474
  • 7
  • 42
  • 50