关于服务端性能、.NET 4.5和Bing
支持Bing和Yahoo的服务器占据美国网络搜索市场超过33%的份额,这是.NET 4.5 RC应用程序最大型的持续正式使用。微软的Bing和.NET团队紧密合作,做出了一系列改善,这对于运行大规模.NET服务器的人们非常有用。
在一次Channel 9的采访中,“.NET GC开发者Maoni Stephens、性能架构师Vance Morrison和Bing的前端开发者Mukul Sabharwal参与进来,一起讨论实践中的.NET 4.5。” 最有趣的重点特性是多线程的JIT编译器。我们不会认为JIT对于服务器很重要,因为它可能会在很长时间保持在线。但是由于ASP.NET框架的原因,像 Ngen之类的技术无法很好地工作。可能会有上百甚至上千个使用Razor或者Web表单编写的视图,而NGen无法查看。每次重启服务器或者进程被回收的时候,所有这些程序都需要重新编译。
有了.NET 4.5和多线程的JIT,我们发现Bing的启动时间减少了一半。这种成果大多数来自于保留了之前JIT编译过组件的列表。这个列表会用于在启动时在后台 提前处理JIT代码。为了避免干扰实际运行代码的线程,即便有更多内核可用,JIT线程能够使用的也被限制在二到三个。
.NET 4.5中主要的重点就是对Windows的事件跟踪(Event Tracing for Windows),或者叫做ETW。这种支持的一部分来自于新引入的EventSource类, 它让.NET应用程序可以创建自己的ETW事件。另一项改进在于堆栈跟踪领域。在之前的版本中,ETW无法在64位服务器上对于没有预编译的代码(例 如,.NET或JavaScript)提供精确地堆栈跟踪信息。有了.NET 4.5和Windows Server 2012,现在就可以提供堆栈跟踪信息,而不需要附加调试器。
不幸的是,随着异步编程的增多,引入了新的问题。在异步模型下面,处理请求的线程不一定是创建请求的线程。这会产生新的堆栈跟踪信息,难于和资源请求的发出者相匹配。除了在这个领域增加了更多工具之外,微软还开始使用PrefView对可视化工具创建原型,期望可以阐明这种问题。最终,微软会把该项支持移动到Visual Studio中。
采访的下一部分涉及到后台垃圾回收器(GC),那在.NET 4.5服务器应用程序中会默认开启。他们谈到了关于固定内存(pinned memory)经常出现的问题。为了决定固定内存真正的消耗有多少,现在每次创建或者修改固定处理器(pinning handler)的时候都会触发ETW事件。
.NET中的固定对象并不一定很昂贵。只有它们恰好位于垃圾回收器想要移动的内存块中的时候,才会导致问题。所以微软现在建议,经常需要固定的对象 (例如,异步缓存)应该被重用。如果你那么做,只是在必要的时候才固定,最终它们就会生成两个带有其他长期存在对象的堆,并且不需要移动。
另外一种方法是,只分配非托管的缓存,把它交给操作系统,而不是固定托管的缓存。这里的取舍是,你需要付出每次把缓存复制到托管内存中的代价,这样就不需要付出针对固定内存运行垃圾回收器的代价。
长期以来微软想要提供某种框架支持,来创建可重用的缓冲池。
关于.NET的垃圾回收器还提到了以下内容:
- 在32位的操作系统下,.NET堆大约是2GB。而使用64位的操作系统,微软认为使用10GB的堆都不常见,甚至有些客户报告使用50GB的堆。但是,如果你想要使用大于2GB的单个数组,就需要启用gcAllowVeryLargeObjects设置。
- 在.NET服务器垃圾回收器中,有一种每个堆一个逻辑处理器的方式。小对象堆会在必要的时候重新平衡,但是在.NET 4.5之前大对象堆不会这么处理。
- 当使用具有多个CPU组的NUMA架构时,应该开启GCCpuGroup设定。
- 在性能很重要的操作中,可以使用SustainedLowLatency模式临时关闭垃圾回收器。