Hi Kim,

On 03/23/2016 09:40 PM, Kim Barrett wrote:
I don't think there's any throughput penalty for a long timeout.  The
proper response to waitForCleanups returning false (assuming the epoch
was obtained early and passed as an argument) is OOME.  I really doubt
the latency for reporting OOME is of critical importance.

The above assumption is not entirely correct. The correct response to waitForCleanups returning false should be at least one attempt to trigger GC reference discovery 1st and only after that it should be OOME. Suppose a program tries to allocate direct memory above the limit. Waiting for cleanups to happen might be very long if there's no heap memory pressure although there might be already lots of unreachable direct buffers on the heap.

So guessing the right timeout before attempting to trigger GC is not trivial. If you make it to small, there will be excessive GCs triggered and throughput will suffer. If you make it to long, throughput will suffer again.

Nevertheless I managed to create a variant that self-adjusts the timeout based on the last successful wait time. At least with the DirectBufferAllocTest using 16 or 32 allocating threads (on 4-core CPU) the throughput is comparable as before and what's important, the test passes:

java -XX:MaxDirectMemorySize=128m -cp out DirectBufferAllocTest -r 600 -t 16 -p 5000 Allocating direct ByteBuffers with capacity 1048576 bytes, using 16 threads for 600 seconds, printing the average per-thread latency of 5000 consecutive allocations...
Thread 11:  1.94 ms/allocation
Thread  6:  1.97 ms/allocation
Thread 12:  2.05 ms/allocation
Thread  0:  2.10 ms/allocation
Thread  7:  2.15 ms/allocation
Thread  3:  2.16 ms/allocation
Thread  1:  2.26 ms/allocation
Thread  5:  2.32 ms/allocation
Thread  2:  2.33 ms/allocation
Thread  4:  2.34 ms/allocation
Thread 13:  2.36 ms/allocation
Thread  9:  2.38 ms/allocation
Thread 14:  2.40 ms/allocation
Thread 10:  2.40 ms/allocation
Thread  8:  2.42 ms/allocation
Thread 15:  2.44 ms/allocation
Thread  6:  1.72 ms/allocation
Thread 11:  1.75 ms/allocation
Thread 12:  1.86 ms/allocation
Thread  0:  1.86 ms/allocation
Thread  3:  1.94 ms/allocation
Thread  7:  2.07 ms/allocation
Thread  1:  2.08 ms/allocation
Thread  2:  2.12 ms/allocation
Thread  4:  2.14 ms/allocation
Thread  5:  2.16 ms/allocation
Thread  9:  2.13 ms/allocation

Here's the webrev:

http://cr.openjdk.java.net/~plevart/jdk9-dev/removeInternalCleaner/webrev.10.part2/

So what do you think?

Regards, Peter


That is, the caller looks something like (not even pretending to write
Java)

   alloc = tryAllocatation(allocSize)
   if alloc != NULL
     return alloc
   endif
   // Maybe add a retry+wait with a short timeout here,
   // to allow existing cleanups to run before requesting
   // another gc.  Not clear that's really worthwhile, as
   // it only comes up when we get here just after a gc
   // and the resulting cleanups are not yet all processed.
   System.gc()
   while true
     epoch = getEpoch()
     alloc = tryAllocation(allocSize)
     if alloc != NULL
       return alloc
     elif !waitForCleanup(epoch)
       throw OOME  // No cleanup progress for a while
     endif
   end

Reply via email to