Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2011-10-31) 大列表对于GC的影响

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

程序中有一个大列表,里面保存了300,000个长期存活的对象,不会被GC清除。那么,这些对象会不会对GC造成影响?比如,让每次GC都花费很多的时间?

因为GC时需要检查对所有对象的引用,所以我担心检查太多的对象,需要花很多时间。


写一个测试程序:

public class ListAddGc {

public static void main(String[] args) throws Exception {     
    List<Long> list = new ArrayList<Long>(300000);      
    for (int i = 0; i < 300000; i++) {      
        long start = System.nanoTime();      
        list.add(start);      
        long end = System.nanoTime();      
        long cost = end - start;      
    }      
    while (true) {      
        new String("abc");      
    }      
}      

}

该程序持有一个300000元素的list,然后通过不断生成新的String来触发GC操作。结果如下:

[GC 281K->146K(15872K), 0.0028494 secs]
[Full GC 146K->146K(15872K), 0.0096386 secs]
[GC 43689K->43598K(55000K), 0.0258150 secs]
[GC 48078K->43897K(55000K), 0.0048889 secs]
[GC 48377K->43897K(55000K), 0.0017662 secs]
[GC 63929K->43897K(72536K), 0.0003661 secs]
[GC 63929K->43897K(72536K), 0.0003503 secs]
[GC 63929K->43897K(72536K), 0.0000992 secs]
[GC 63929K->43897K(72536K), 0.0003927 secs]
[GC 63929K->43897K(72536K), 0.0003651 secs]
[GC 63929K->43897K(72536K), 0.0003592 secs]
[GC 63929K->43897K(72536K), 0.0003760 secs]
[GC 63929K->43897K(72536K), 0.0001119 secs]
[GC 63929K->43897K(72536K), 0.0004512 secs]
[GC 63929K->43897K(72536K), 0.0003288 secs]

可见每次普通GC花费的时间极小,可以忽略。通过观察后面的数据,发现很少发生Full GC。

于是我打开jvisualvm,通过它提供的“执行GC”按钮来触发Full GC。显示如下:

[Full GC 16199K->740K(72536K), 0.0374200 secs]

使用大约37ms。考虑到jvisualvm的影响,不使用jvisualvm,而修改代码,主动触发GC。代码如下:

for (int i = 0;; i++) {

new String("abc");      
if (i % 1000 == 0) {      
    System.gc();      
}      

}

显示如下:

[Full GC 43960K->146K(55000K), 0.0133591 secs]
[Full GC 551K->146K(72536K), 0.0114220 secs]
[Full GC 520K->146K(66904K), 0.0114949 secs]
[Full GC 406K->146K(46508K), 0.0112917 secs]
[Full GC 237K->146K(15936K), 0.0114735 secs]
[Full GC 237K->146K(15936K), 0.0104386 secs]
[Full GC 237K->146K(15936K), 0.0107348 secs]
[Full GC 237K->146K(15936K), 0.0120792 secs]

可见每次Full GC使用的时间约为10ms,可接触。考虑到只要设置了足够的Xmx,Full GC并不会经常发生。所以我认识使用一个大列表拥有对象,并不会对GC造成多大影响。

更多的讨论见我在stackoverflow上的提问:

http://stackoverflow.com/questions/7949591/if-there-is-a-list-holding-300-000-objects-all-the-time-will-gc-have-a-bad-perf

comments powered by Disqus