Skip to content

Instantly share code, notes, and snippets.

@arrayadd
Created August 2, 2017 12:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arrayadd/0ff0a468f1e201422d5264ac350f9ab1 to your computer and use it in GitHub Desktop.
Save arrayadd/0ff0a468f1e201422d5264ac350f9ab1 to your computer and use it in GitHub Desktop.
分配担保意义

我们知道HotSpot虚拟机把堆空间(内存上可以是不连续的)分成不同区域,来进行所谓分代收集。 其中又根据来自IBM一些数据研究结果,把一些朝生夕死的短命鬼划分到年轻代,其他一些老不死的放到老年代。 当年轻代存不下新分配对象时候,就会触发所谓的Minor GC,进而引发老年代和新生代之间的分配担保机制

关于分配担保机制的详细过程,网上充栋,这里就不说了,但更有意思是,这种机制不需要可以吗?使用了它又有什么意义?实际工作场景中有没有可以参考的。


为什么需要是连续的空间

分配担保机制中,无论是新生代所有对象总和还是历次晋升到老年代的平均大小的经验值,在进行比较时候都会和老年代最大连续空间进行比较。 难道不连续只要凑起来够就不行了?毕竟老年代还是**标记-清理-(压缩)**算法。

确实不行,因为:

  • 新生代的复制算法机制决定了需要连续空间。因为分配担保机制进行时候,还没有发生Minor GC,这时候经过上次复制清理出来的空间,虽然分配了新对象,但这些对象很大程度上是连续的。一旦担保成功,显然直接复制过去最快速。
  • JVM中对象的分配和回收是非常高频事情,直接决定其性能。如果为了追求理论上的合理性,来为每一个新生代晋升对象,在老年带零碎的空间中寻找能放得下空间,将会是一件非常耗时繁琐事情,况且同样是一块1Mb大小空间,到底是放一个0.8Mb的对象,还是继续遍历完所有晋升对象,比较后只为找一个更接近1Mb的。所以效率上是不允许。

去掉分配担保机制可以吗

从分配担保的逻辑中,可以看出

分配担保最关键作用是,在进行Minor GC前是否需要根据历届晋升到老年代的平均值来发起一次Full GC. 换句话来说,去掉分配担保(也就是相当于参数HandlePromotionFailure=false)就意味着Full GC发生的几率更大。

所以结论:分配担保机制可以不要,但会导致Full GC更容易发生,进而导致所谓的Stop The World,虚拟机短暂停止,吞吐量,性能下降。 有了分配担保机制,就可以借鉴经验值来减少Full GC这种耗时降低性能行为。


实际业务有什么借鉴

JVM中使用分配担保机制的思路就是,使用经验值(历次晋升的平均大小)来降低系统耗资源,低效的操作(Full GC). 之前写了一篇文章,其中使用的是随机数来减少耗资源操作(数据delete,常常意味着锁行或表) 记一个需求开发的思维过程

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment