试着把.net的GC讲清楚(3)

root

第一篇文章中讲了GC在遍历存活对象的时候,都是从root开始的,root是一些对象的引用,例如:全局对象、静态对象等。

如果要减少root的个数,那么就可以从静态对象入手,减少静态对象,毕竟静态对象一直存活到程序结束。

全局对象为什么不考虑?原因很简单,就是静态对象更容易优化,全局对象的一个程序中也没有几个,如果优化过程中,必然需要把全局对象的内容放到其它的地方,例如塞到另一个类里面,那么会造成这个类膨胀起来。
当然这也是一种方法。

LOH

之前了解到>=85000个字节的对象,会放到大对象的堆里面,并且在gen2回收的时候才进行回收,且不进行内存压缩,内存稍紧张的时候,就会造成少许浪费,所以
这个我们需要控制对象的体积,让它尽可能<85000。

gen0、gen1、gen2

当gc触发回收gen0的时候,那么此次存活的对象会升代,理想情况让gen0的大小在一次回收过程中,就可以得到内存空间,也就是需要减少一个对象的生存周期,让对象的生存周期尽可能短。

在生存周期非常短的情况,那么gen0的回收一次会获取很大的内存空间,且升代的对象非常少,那么gc就没有必要再向OS申请内存资源了。

gc申请内存资源

在创建对象的时候,gc在自己可用内存不够的情况下,会向os申请新的内存资源,并在gc回收内存后,并不会返回内存给os。所以就如之前的前一节说的,减少对象
可以让os有更多的可调配资源。

Weak Reference

在GC回收的时候,weak reference的对象是会被当做垃圾的,所以这个慎用,基于这个特性,在某些场景下,weak reference的对象在使用的时候可以进行判断是否已经被回收。
如果回收了,那么重新在申请,比如某些占内存的外部资源,就可以使用weak reference来减少内存紧张带来的问题。

finalize方法

还记得一个对象含有finalize方法的特点吗?需要GC两次才可能被回收,且GC的时间不定,所以非托管资源尽可能不使用finalize,对于内存紧张的情况,就不要使用了,不然
需要2次gc,gc的时候程序性能特别差。

workstation、server gc mode

保守的资源用workstation gc mode,非保守的资源用server gc mode,然后在用用cocurrent方式提升一下gc的性能,减少程序执行挂起时间。

总结

用理论指导实际,需要场景来支持,现在很多的程序的各种结构和算法都是为了提高性能而设计的,所以为了性能,很多的架构或者程序算法还有其他的辅助功能,也是很合理了。

posted @ 2018-03-03 10:14 奔跑的Abbott 阅读(...) 评论(...) 编辑 收藏