18

How do I check if ConcurrentLinkedQueue leaves the garbage (referrals) for the G...

 3 years ago
source link: https://www.codesd.com/item/how-do-i-check-if-concurrentlinkedqueue-leaves-the-garbage-referrals-for-the-gc.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How do I check if ConcurrentLinkedQueue leaves the garbage (referrals) for the GC?

advertisements

I am using a bunch of ConcurrentLinkedQueues in my application and the GC overhead is huge. How do I check if the ConcurrentLinkedQueue is the culprit? Is there a standard way in Java to profile these data structures for memory allocation/deallocation?


One way to do it is to write a simple test program and run it with the -verbose:gc JVM option. For example, the code:

import java.util.concurrent.ConcurrentLinkedQueue;

public class TestGC {

    public static void main(String[] args) throws Exception {

        final ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();

        String[] strings = new String[1024];

        for(int i = 0; i < strings.length; i++) {
            strings[i] = "string" + i;
        }

        System.gc();
        Thread.sleep(1000);

        System.out.println("Starting...");

        while(true) {
            for(int i = 0; i < strings.length; i++) queue.offer(strings[i]);
            for(int i = 0; i < strings.length; i++) queue.poll();
        }
    }
}

Produces the output:

$ java -verbose:gc TestGC
[GC 1352K->560K(62976K), 0.0015210 secs]
[Full GC 560K->440K(62976K), 0.0118410 secs]
Starting...
[GC 17336K->536K(62976K), 0.0005950 secs]
[GC 17432K->536K(62976K), 0.0006130 secs]
[GC 17432K->504K(62976K), 0.0005830 secs]
[GC 17400K->504K(62976K), 0.0010940 secs]
[GC 17400K->536K(77824K), 0.0006540 secs]
[GC 34328K->504K(79360K), 0.0008970 secs]
[GC 35320K->520K(111616K), 0.0008920 secs]
[GC 68104K->520K(111616K), 0.0009930 secs]
[GC 68104K->520K(152576K), 0.0006350 secs]
[GC 109064K->520K(147968K), 0.0007740 secs]
(keeps going forever)

Now if you want to know exactly who is the culprit you can use a profiling tool. I wrote this memory sampler that you can plug in your code to quickly find out in what source code line the instances are being created. So you do:

MemorySampler.start();
for(int i = 0; i < strings.length; i++) queue.offer(strings[i]);
for(int i = 0; i < strings.length; i++) queue.poll();
MemorySampler.end();
if (MemorySampler.wasMemoryAllocated()) MemorySampler.printSituation();

And when you run you get:

Starting...
Memory allocated on last pass: 24576
Memory allocated total: 24576

Stack Trace:
    java.util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:327)
    TestGC.main(TestGC2.java:25)

From where you can see that line 327 of ConcurrentLinkedQueue is leaking instances for the GC, in other words, it is not pooling them:

public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);

    for (Node<E> t = tail, p = t;;) {




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK