GC悲观策略之Parallel GC篇

Posted on

GC悲观策略之Parallel GC篇

BlueDavy之技术blog

{互联网,OSGi,Java, High Scalability, High Performance,HA}

GC悲观策略之Parallel GC篇

Nov 07

bluedavyjvm gc, jvm, pessimism policy, 悲观策略 12 Comments 先来看段代码: ?1

2 3

4 5

6 7

8 9

10 11

12 13

14 import

java.util./*;

public

class

SummaryCase{

public

static

void

main(String[] args)

throws

Exception{

List caches=

new

ArrayList();

for

(

int

i=

0

;i<

7

;i++){

caches.add(

new

byte

[

1024

/*

1024

/*

3

]);

}

caches.clear();

for

(

int

i=

0

;i<

2

;i++){

caches.add(

new

byte

[

1024

/*

1024

/*

3

]);

}

Thread.sleep(

10000

);

}

}

当用-Xms30m -Xmx30m -Xmn10m -XX:+UseParallelGC执行上面的代码时会执行几次Minor GC和几次Full GC呢? 按照eden空间不足时触发minor gc的规则,上面代码执行后的GC应为:M、M、M、M,但实际上上面代码执行后GC则为:M、M、M、F、F。 这里的原因就在于Parallel Scavenge GC时的悲观策略,当在eden上分配内存失败时且对象的大小尚不需要直接在old上分配时,会触发YGC,代码片段如下:

?1

2 3

4 5

6 7

8 9

10 11

12 13

14 15

16 17

18 19

20 21

22 23

24 25

26 27

28 29

30 31

32 33

34 35

36 37void

PSScavenge::invoke(){

... bool

scavenge_was_done = PSScavenge::invoke_no_policy();

PSGCAdaptivePolicyCounters/* counters = heap->gc_policy_counters(); if

(UsePerfData)

counters->update_full_follows_scavenge(0); if

(!scavenge_was_done ||

policy->should_full_GC(heap->old_gen()->free_in_bytes())) { if

(UsePerfData)

counters->update_full_follows_scavenge(full_follows_scavenge);<

GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy); if

(UseParallelOldGC) {

PSParallelCompact::invoke_no_policy(

false

); }

else

{

PSMarkSweep::invoke_no_policy(

false

); }

} ...

} PSScavenge::invoke_no_policy{

... if

(!should_attempt_scavenge()) {

return

false

; }

... }

bool

PSScavenge::should_attempt_scavenge() { ...

PSAdaptiveSizePolicy/* policy = heap->size_policy();

size_t

avg_promoted = (

size_t

) policy->padded_average_promoted_in_bytes(); size_t

promotion_estimate = MIN2(avg_promoted, young_gen->used_in_bytes());

bool

result = promotion_estimate < old_gen->free_in_bytes(); ...

return

result; }

在上面should_attempt_scavenge代码片段中,可以看到会比较之前YGC晋升到Old中的平均大小与当前新生代中已被使用的字节数大小,取更小的值与旧生代目前剩余空间大小对比,如更大,则返回false,就终止了YGC的执行了,当返回false时,PSScavenge::invoke就将触发Full GC了。 在PSScavenge:invoke中还有一个条件为:policy->should_full_GC(heap->old_gen()->free_in_bytes(),来看看这段代码片段:

?1

2 3

4 5bool

PSAdaptiveSizePolicy::should_full_GC(

size_t

old_free_in_bytes) {

bool

result = padded_average_promoted_in_bytes() > (

float

) old_free_in_bytes; ...

return

result; }

可看到,这段代码检查的也是之前YGC时晋升到old的平均大小是否大于了旧生代的剩余空间,如大于,则触发full gc。 总结上面分析的策略,可以看到采用Parallel GC的情况下,当YGC触发时,会有两个检查: 1、在YGC执行前,min(目前新生代已使用的大小,之前平均晋升到old的大小中的较小值) > 旧生代剩余空间大小 ? 不执行YGC,直接执行Full GC : 执行YGC; 2、在YGC执行后,平均晋升到old的大小 > 旧生代剩余空间大小 ? 触发Full GC : 什么都不做。

按照这样的说明,再来看看上面代码的执行过程中eden和old大小的变化状况: 代码 eden old YGC FGC 第一次循环 3 0 0 0 第二次循环 6 0 0 0 第三次循环 3 6 1 0 第四次循环 6 6 1 0 第五次循环 3 12 2 0 第六次循环 6 12 2 0 第七次循环 3 18 3 1 第八次循环 6 18 3 1 第九次循环 3 3 3 2 在第7次循环时,YGC后旧生代剩余空间为2m,而之前平均晋级到old的对象大小为6m,因此在YGC后会触发一次FGC。 而第9次循环时,在YGC执行前,此时新生代已使用的大小为6m,之前晋级到old的平均大小为6m,这两者去最小值为6m,这个值已大于old的剩余空间,因此就不执行YGC,直接执行FGC了。

Sun JDK之所以要有悲观策略,我猜想理由是程序最终是会以一个较为稳态的状况执行的,此时每次YGC后晋升到old的对象大小应该是差不多的,在YGC时做好检查,避免等YGC后晋升到Old的对象导致old空间不足,因此还不如干脆就直接执行FGC,正因为悲观策略的存在,大家有些时候可能会看到old空间没满但full gc执行的状况。 埋个伏笔,大家将上面的执行参数换为-XX:+UseSerialGC执行看看,会发生什么呢? :)

JavaOne美国之行–硅谷公司交流篇 GC悲观策略之Serial GC篇

12 Comments (+add yours?)

  1. xan Nov 08, 2010 @ 11:58:44 代码布局不怎么给力啊 :)
  2. bluedavy Nov 08, 2010 @ 12:23:52 确实不给力,我折腾下。
  3. imbeneo Nov 08, 2010 @ 13:12:45 我忘记了clean,结果总是OOM。
  4. oliver Apr 26, 2011 @ 11:34:35 我的疑问是为什么第一次full gc时old里面使用空间没有被回收掉,第二次full gc时old里面才回收?
  5. bluedavy Apr 26, 2011 @ 13:32:18 因为caches.clear是后来才调的…
  6. yinhex Jul 09, 2011 @ 22:38:20 这里我有个问题啊:我看你的分布式基础看到你能举例出很多大网站的设计。不知道你是从哪里可以看到这些信息的呢?可以细数一下你经常上去获取信息国外网站吗?
  7. bluedavy Jul 11, 2011 @ 10:01:48 @yinhex 一般来说,例如highscalability.com,还有各种国外的技术大会,各家著名公司的engineer的blog,都会有这些信息,:)
  8. Gary Sep 29, 2011 @ 11:09:58 -XX:+UseSerialGC gc.log发现是MMMMF,符合预期啊
  9. yangxuesong Nov 29, 2011 @ 17:31:49 一次full gc的执行流程是怎么用的呢?
  10. bluedavy Dec 03, 2011 @ 11:10:22 @yangxuesong 这个…要看是什么垃圾收集器…

    Leave a Reply

Cancel

Name (required)

Mail (required)

Website

CAPTCHA Image

Refresh Image

CAPTCHA Code /*


July 2013 M T W T F S S « Mar 1234567 891011121314 15161718192021 22232425262728 293031

Categories

Tags

btrace c1 c2 Deflater facebook gc gc tuning Grizzly HBase hotspot Inflater interpreter javac java code generation JavaOne javaone general technical session java代码执行 Java 并发 jit jvm memory management Native Memory Leak NoSQL oom oracle keynote pessimism policy references RPC serial gc SOA sun jdk sun jdk oom Web容量规划的艺术 yuanzhuo 书:分布式Java应用 书评 互联网技术 交流 内存管理 分布式Java应用 圆桌交流 容量规划 悲观策略 服务框架 硅谷公司

订阅

推荐书籍

My Book

© BlueDavy之技术blog 2013

Icons & Wordpress Theme by N.Design

希望本站内容对您有点用处,有什么疑问或建议请在后面留言评论
转载请注明作者(RobinChia)和出处 It so life ,请勿用于任何商业用途
无觅关联推荐,快速提升流量