Menu

Understanding Threadpool.nextIndex()

Developers
Luke S
2016-11-04
2016-11-06
  • Luke S

    Luke S - 2016-11-04

    Hey there! This question is primarily for Peter, but anyone who has the background to understand is welcome to Chime in.

    I was recently doing some profiling during the creation of a Photon map, and I noticed something interesting: A lot of the worker threads were getting blocked at Threadpool.nextIndex(). I was intrigued, because they were all blocking at the same location, line 230. For easy reference, the method is below:

      private int nextIndex() throws InterruptedException
      {
        int index;
        while ((index = nextIndex.getAndIncrement()) >= numIndices)  //line 214
        {
          // Wait until run() is called again.
    
          synchronized (this)
          {
            waitingThreads.add(Thread.currentThread());
            if (waitingThreads.size() == thread.length)
            {
              while (!controllerWaiting)
                wait(1);
              synchronized (controller)
              {
                controller.notify();
              }
            }
            wait();  ///line 230
          }
        }
        return index;
      }
    

    I'm trying to understand the intent of the code here. I realise that each thread needs an index to identify its current task.

    This code seems to make each thread wait until all of them are in line for a new task. Am I understanding this properly, and if so, why? Could not each thread be sent off on a new task as soon as it has completed the old one?

    The reason that this comes up is that some testing showed on my system that the Photon mapping threads start stepping on each other pretty hard in this method. They keep my entire cpu (8 cores/threads) pegged at 100% usage, shuttling in and out of this wait() state, and only get about 2 threads worth of work done, compared to a single thread. Even two threads show some contention here.

     
  • Peter Eastman

    Peter Eastman - 2016-11-04

    If they're waiting at that line, it means there's no more work for them to do. Notice the whole block starting at line 214 only gets executed if index >= numIndices. That means the threads have already gone through all the work that was available to do, so they all just call wait() and go to sleep until run() gets called again.

    When a thread is asleep it doesn't use any CPU, so I don't think that's responsible for the 100% usage. Some other threads are keeping the CPU busy. Which of course is exactly what you want. The goal is to keep the CPU usage as close to 100% as possible all the time.

     
  • Luke S

    Luke S - 2016-11-06

    Thanks for the explanation. That makes a lot more sense! - I had the guarding backwards in my mind.

    I checked over my thread data more thouroughly, and I need to be a bit more precise:

    When running certain PM tasks, (In particular, generating photons from an environment map) I will often see several threads Blocked, presumably trying to get access to the object lock so that they can enter the wait().

    I've compared to circumstances when threads have already ended up in waiting status, and they are different. No other activity on the system at the time, and the CPU usage is real (Measured at the OS level, not in the JVM)

    I think I know what is happening, but need to do some tests.

     

Log in to post a comment.