RFR (S) CR 6857566: (bf) DirectByteBuffer garbage creation can outpace reclamation

Peter Levart peter.levart at gmail.com
Wed Oct 2 15:58:54 UTC 2013


Hi Aleksey,

I briefly skimmed over the changes. If I understand them correctly, they 
change they way Cleaners are processed. Without any assistance from 
other threads, Cleaners (WeakReferences now) are 1st enqueued by the 
ReferenceHandler thread, and CleaningThread then picks them out of the 
queue and processes them. Because they are not processed by 
ReferenceHandler thread any more, cleaning does not interfere with 
en-queueing of other References. This is good.

Assisting cleaning from other threads means that cleaning can be 
performed in any thread. Cleaners should be prepared for that - 
previously they were only invoked from ReferenceHandler thread.

assistCleanupSlow could really become slow, if lots of Cleaners get 
allocated (for example, lots of small DirectByteBuffers get allocated) 
and not GC-ed for some time.

This brings me to java.nio.Bits. It uses System.gc(). I understand that 
allocation  of native memory does not represent a memory pressure for 
heap GC so you're trying to trigger it when it gets tight. But lots of 
environments (app servers) are using -XX:+DisableExplicitGC to prevent 
ill behaved libraries to trigger GCs to frequently. Have you tried your 
test using -XX:+DisableExplicitGC ?

Regards, Peter

P.S.

I wish there was some Java-side API with which you could register (with 
enough privilege) a filter that would decide whether to honour 
System.gc() or not (making System.gc() @CallerSensitive and invoking a 
registered Predicate<Class<?>>-s with the caller class, for example. If 
any of registered Predicates returned true, the gc would be honoured). 
App servers could use this API instead of -XX:+DisableExplicitGC then.


On 10/02/2013 04:43 PM, Aleksey Shipilev wrote:
> Hi,
>
> There is the issue that annoys me all the time:
>    https://bugs.openjdk.java.net/browse/JDK-6857566
>
> Please review the rework of DirectByteBuffer cleanup mechanics fixing
> that issue. Since DBB uses sun.misc.Cleaner as the infrastructure to
> clean up things, we focus there:
>    http://cr.openjdk.java.net/~shade/6857566/webrev.00/
>
> Brief explanation is there in Cleaner comments.
>
> Testing:
>    - jtreg: jdk/nio tests on Linux x86_64/fastdebug
>    - original sample test from 6857566, reproduces in a few seconds
> nicely with -XX:MaxDirectMemorySize=16M; more than 90 minutes run with
> patched build yield no OOMEs!
>    - microbenchmarking, see below
>
> The microbenchmark tests allocates ByteBuffer.allocateDirect(N), with
> N=1,10,100,1000 bytes:
>    http://cr.openjdk.java.net/~shade/6857566/directbb/
>
> On my 2x2 i5 Linux x86_64 laptop:
>
> Before patch (1 thread):
>   direct_1         834 +- 159 ns/op
>   direct_10        888 +- 262 ns/op
>   direct_100       969 +- 307 ns/op
>   direct_1000     1618 +-  46 ns/op
>
> Before patch (4 threads):
>   direct_1       <OOME!>
>   direct_10      <OOME!>
>   direct_100     <OOME!>
>   direct_1000    <OOME!>
>
> Single threaded allocators are working fine, but this means nothing,
> because more threads just plainly OOME.
>
> After patch (1 thread):
>   direct_1        1645 +- 68 ns/op
>   direct_10       1623 +- 53 ns/op
>   direct_100      1704 +- 44 ns/op
>   direct_1000     3327 +- 43 ns/op
>
> After patch (4 threads):
>   direct_1        4673 +- 80    ns/op
>   direct_10       4673 +- 114   ns/op
>   direct_100      4771 +- 89    ns/op
>   direct_1000    22310 +- 14390 ns/op
>
> Thanks,
> -Aleksey.




More information about the core-libs-dev mailing list