求助>MinMetaspaceExpansion和MaxMetaspaceExpansion这俩个参数到底是什么意思?>
9回复
1月前

MinMetaspaceExpansion和MaxMetaspaceExpansion这俩个参数到底是什么意思?



今天在看你假笨大神的文章:JVM源码分析之Metaspace解密,里面有一段内容我理解不动。就是下面这部分内容

MinMetaspaceExpansion
MinMetaspaceExpansion和MaxMetaspaceExpansion这两个参数或许和大家认识的并不一样,也许很多人会认为这两个参数不就是内存不够的时候,然后扩容的最小大小吗?其实不然
这两个参数和扩容其实并没有直接的关系,也就是并不是为了增大committed的内存,而是为了增大触发metaspace GC的阈值
这两个参数主要是在比较特殊的场景下救急使用,比如gcLocker或者should_concurrent_collect的一些场景,因为这些场景下接下来会做一次GC,相信在接下来的GC中可能会释放一些metaspace的内存,于是先临时扩大下metaspace触发GC的阈值,而有些内存分配失败其实正好是因为这个阈值触顶导致的,于是可以通过增大阈值暂时绕过去
默认332.8K,增大触发metaspace GC阈值的最小要求。假如我们要救急分配的内存很小,没有达到MinMetaspaceExpansion,但是我们会将这次触发metaspace GC的阈值提升MinMetaspaceExpansion,之所以要大于这次要分配的内存大小主要是为了防止别的线程也有类似的请求而频繁触发相关的操作,不过如果要分配的内存超过了MaxMetaspaceExpansion,那MinMetaspaceExpansion将会是要分配的内存大小基础上的一个增量。
MaxMetaspaceExpansion
默认5.2M,增大触发metaspace GC阈值的最大要求。假如说我们要分配的内存超过了MinMetaspaceExpansion但是低于MaxMetaspaceExpansion,那增量是MaxMetaspaceExpansion,如果超过了MaxMetaspaceExpansion,那增量是MinMetaspaceExpansion加上要分配的内存大小。
注:每次分配只会给对应的线程一次扩展触发metaspace GC阈值的机会,如果扩展了,但是还不能分配,那就只能等着做GC了。
微信截图_20211016152022.png

MinMetaspaceExpansion和MaxMetaspaceExpansion这俩个参数的作用到底是什么?谁能举个例子来解释一下?

948 阅读
请先登录,再评论

在每次GC完之后都会重新计算触发GC的阈值(因metaspace空间触发的),这个阈值的调整会受到MinMetaspaceExpansion和MaxMetaspaceExpansion的影响,到底扩大到多少比较合适

1月前
回复 豆大侠:

好像懂了,非常感谢豆神。

1月前回复
回复 四千岁:

你这块的疑问在于你不理解Metaspace的空间的构成,如果你看过GC日志就会发现其实Metaspace分used, capacity, committed和reserved(这块有不少文章讲述可以看看,我就不再赘述了)。Metaspace和Perm一个重要的区别就在于Perm的内存是一开始就分配好的,而Metaspace一开始只分配了很小的空间。在分配新的metaspace空间的时候会从reserved中申请新的MetaChunk,而这个chunk一旦被申请下来之后就会被committed,即使后面这个chunk被释放了也不会还给os,而是把这个chunk加入到一个freelist里面(以后再申请chunk时优先从freelist中拿),这个committed的值就是HWM(high water mark)或者说 _capacity_until_GC,即我们通常意义上说的MetaspaceGC的阈值(这个特性也是笨神文章建议设置MaxMetaSpaceSize的原因,不做限制memory leak的时候能一直申请内存导致oom killer)。
你在申请分配新的metaspace空间的时候,只要committed的值还没有达到你设定的阈值(一开始是MetaspaceSize),他就会一直申请新的chunk,一直扩展committed,这时候是不存在申请失败的情况的,只有在committed到达了设定的阈值,才会出现申请失败的情况,而这个时候才会触发Full GC(可以看看源码的VM_CollectForMetadataAllocation::doit()部分逻辑)。
笨神的文章其实已经描述的很清楚了,在那两种特殊情况下即将迎来一次GC可能会释放一部分Metaspace的内存,所以此时调大一些阈值尽可能的避免一些因为到达阈值分配失败导致的GC(当然有可能避免不了)。

1月前回复
回复 四千岁:

而有些内存分配失败其实正好是因为这个阈值触顶导致的,这句话我很不理解。内存分配失败是看metaspace的剩余空间的,不是看这个阈值的吧。难道我要分配100M的metaspace内存空间,我不看metaspace的剩余空间到底有没有100M,而是看这个阈值有没有100M?

1月前回复
查看更多