C#内存管理优化畅想(二)----巧用堆栈

11/25/2015来源:ASP.NET技巧人气:1046

    这个优化方法比较易懂,就是对于仅在方法内部用到的对象,不再分配在堆上,而是直接在栈上分配,方法结束后立即回收,这将大大减轻GC的压力。

    其实,这个优化方法就是java里的逃逸分析,不知为何.net里没有引入。

英文讨论贴:https://github.com/dotnet/coreclr/issues/1784

附注:逃逸分析优化JVM原理(转自http://f.dataguru.cn/thread-346269-1-1.html)

我们知道java对象是在堆里分配的,在调用栈中,只保存了对象的指针。

当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量较多,将给GC带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。
接下来,举一个场景来阐述。
假设在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸(在方法体内,未将引用暴露给外面)。
按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。
这是优化前,JVM的处理方式。
逃逸分析优化 – 栈上分配
优化原理:分析找到未逃逸的变量,将变量类的实例化内存直接在栈里分配(无需进入堆),分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量也被回收。
这是优化后的处理方式,对比可以看出,主要区别在栈空间直接作为临时对象的存储介质。从而减少了临时对象在堆内的分配数量。
逃逸分析另一个重要的优化 – 锁省略
如果通过逃逸分析能够判断出指向某个局部变量的多个引用被限制在同一方法体内,并且所有这些引用都不能“逃逸”到这个方法体以外的地方,那么HotSpot会要求JIT执行一项优化动作 – 将局部变量上拥有的锁省略掉。
这就是锁省略(lock elision)。