如何检查ConcurrentLinkedQueue是否为GC留下垃圾(取消引用的实例)? [英] How do I check if ConcurrentLinkedQueue leaves garbage (dereferenced instances) for the GC?

查看:372
本文介绍了如何检查ConcurrentLinkedQueue是否为GC留下垃圾(取消引用的实例)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在应用程序中使用了一堆 ConcurrentLinkedQueue ,GC开销很大。如何检查 ConcurrentLinkedQueue 是否是罪魁祸首?在Java中有没有一种标准的方式来分析这些数据结构以进行内存分配/释放?解析方案

解决方案

编写一个简单的测试程序并使用 -verbose:gc JVM选项运行它。例如,代码:

  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 ...); $(b)b
while(true){
for(int i = 0; i< strings.length; i ++)queue.offer(strings [i]);
for(int i = 0; i< strings.length; i ++)queue.poll();



code
$ b产生输出:

  $ java -verbose:gc TestGC 
[GC 1352K-> 560K(62976K),0.0015210 secs]
[全GC560K-> 440K(62976K),0.0118410秒]
起始...
[GC 17336K-> 536K(62976K),0.0005950秒]
[GC 17432K- (62976K),0.0006130秒]
[GC 17432K-> 504K(62976K),0.0005830秒]
[GC 17400K-> 504K(62976K),0.0010940秒]
[GC 17400K-> 536K(77824K),0.0006540​​秒]
[GC 34328K-> 504K(79360K),0.0008970秒]
[GC 35320K-> 520K(111616K),0.0008920秒]
[GC 68104K-> 520K(111616K),0.0009930秒]
[GC 68104K-> 520K(152576K),0.0006350秒]
[GC 109064K-> 520K(147968K) ,0.0007740秒]
(一直持续下去)

现在如果您想确切知道谁是你可以使用分析工具的罪魁祸首。我写了此内存采样器,您可以插入代码以快速找出正在创建实例的源代码行。所以你这样做:

  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();

而当您运行时,您会得到:

 开始... 
最后一次传递的内存分配:24576
内存分配总计:24576

堆栈跟踪:
java .util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:327)
TestGC.main(TestGC2.java:25)

从这里你可以看到 ConcurrentLinkedQueue 的第327行泄漏了GC的实例,换句话说,它并没有对它们进行池化: p>

  public boolean offer(E e){
checkNotNull(e);
final节点< E> newNode = new Node< E>(e); (节点< E> t = tail,p = t ;;){




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;;) {

这篇关于如何检查ConcurrentLinkedQueue是否为GC留下垃圾(取消引用的实例)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆