[翻译] 编写高性能 .NET 代码--第二章 GC -- 配置选项
配置选项
在基于“less rope to hang yourself with”思想下,.NET 框架没有给开发提供很多太多的配置选项。但在大多数情况下,GC会跟你的硬件配置,及可用资源以及程序自己的行为做调整。当然也提供一些高级的配置使用,但这取决于你程序的类型。
工作站与服务器
你首要的是为应用选择是在工作站还是服务器模式下运行。
系统默认为工作站模式。在这种模式下,GC在触发回收时,回收线程与当前主线程的优先级一样。对于简单的应用程序,特别是存在工作站里有多个托管进程需要做交互的情况下,以及单处理器的计算机上,这可能是唯一的选择,你试图修改任何配置对运行不会产生任何影响。
服务器模式则会给每个业务逻辑进程创建一个专用的线程。这个线程会运行在高优先级(THREAD_PRIORITY_HIGHEST),但平时这个线程会处于休眠状态,一旦需要做GC就会被唤醒。完成GC后又会进入休眠。
此外,CLR还会为每个处理器分配一个单独的堆。每个处理器堆里,包含一个小对象堆和大对象堆。从你的应用程序角度上看,你的代码不知道引用的对象是属于哪个堆上面的(他们都有相同的虚拟地址空间)。
使用多个堆有下一些优点
- 垃圾回收可以并行处理。每个GC线程处理一个对应的堆。这是的服务器模式的GC比工作站模式要快的原因。
- 某些情况下,分配速度会更快,尤其是将大对象相对分配在同一个堆上快。还有一些其他内部差异,比如内存段的大小,越大的段在做垃圾回收时时间也会越长。
你可以在App.config 文件里的节点里配置。
<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>
你要如何选择工作站或者服务器模式吗?
如果一个多处理器机器上只运行你的应用程序,那么最明智的选择是:服务器模式。它在大多数情况下可以降低GC的延迟。
另一位方面,如果你的机器有多个托管进程的应用程序,则需要具体分析了。如果这几个托管应用都采用服务器模式,那么会创建很多个高优先级的线程,这个会对线程调度产生冲突和影响。在这种情况下,最好使用工作站模式。
如果你真的想在同一个台机器里的多个应用程序开启服务器GC模式,还有另外一种选择,就是为应用程序绑定特定的CPU。
无论你选择哪种模式,本书的大部分技巧都使用这两种模式。
后台GC
修改后台GC配置会更改2代对象的回收策略。相对于0代和1代的回收的前台GC,它不会中断当前应用里其他的线程执行。
后台GC在会而外创建一个线程用来处理2代对象的回收。这意味着,如果你同时开启后台GC和服务器GC,你将为每个处理器创建2个线程来处理GC。但这没啥大不了的,虽然进程里多了很多个线程,但这些线程在大部分时间里还是不工作的。
在你的应用执行的时候GC也可以同时进行,但在某些情况下,还是会发生阻塞。在这时,后台GC还是会将应用程序里的其它线程给挂起。
如果使用工作站模式,则始终开启后台GC模式,从.NET4.5开始,默认情况下服务器GC模式下也会开启,当然你也可以关闭它。
以下是关闭后台GC的配置
<configuration>
	<runtime>
		<gcConcurrent  enabled="false"/>
	</runtime>
</configuration>
实际上,我们很少有理由去禁用后台GC。如果你想通过禁用后台GC的线程来提高你的应用程序在CPU的占用率,但这个想法是不现实的。但如果是减少GC的延迟或者频率可以考虑关闭它。
低延迟模式
如果你的应用希望在一段特定时间里高速执行,不希望被GC的2代回收打扰。你可以通过改变 GCSettings.LatencyMode 的设置来实现。
LowLatency—只能在工作站模式运行,它可以暂停2代回收。
SustainedLowLatency—可以在工作站和服务器模式下执行。它可以暂停完整的2代回收,但如果你开启里后台GC模式,你还是可以在后台GC线程里对2代对象做回收。
这两种模式都将大大的增加内存的消耗,因为它没对内存做压缩。如果你的应用需要消耗大量的内存,则最好避免开启这两个模式。
当你要准备进入低延迟模式前,最好手动执行一次完整的GC(GC.Collect(2, GCCollectionMode.Forced)。等离开低延迟模式后,也手动触发一次完成GC。
默认情况下,是不需要开启这个模式。只有你的程序执行时间不要被GC打扰才需要开启,不用在全过程都开启。举个栗子:如果你有一个股票交易的高频应用,在交易时间段里不希望发生GC回收暂停应用执行。但在股市交易结束后,你可以关闭这个模式进行完整的GC回收直到股市重新开市。
如果要开启低延迟模式,至少要符合以下标准:
- 在正常执行期间,完整的垃圾回收操作是不可接受的
- 应用程序消耗的内存要远小于可分配内存
- 应用程序在开启低延迟模式后,要有足够的内存撑到下一次手动执行完整回收或者重启。
这是一个很少用的配置,如果你要使用请三思而后行,因为开启之后会出现一些意想不到的后果。如果你认为还是有必要使用,请确保你的应用经过了充分测试。在开启后,系统会产生更频繁的0代和1代的回收操作,用来减少完整的回收,这可能会导致一些其他性能问题。这可能会导致解决了一个又另外产生了一个问题。
最后,请注意,低延迟模式不是一个保证。如果GC在做回收的时候仍然抛出了OutOfMemoryException异常,仍然有可能会不管你的配置选项,进行一次完整的GC回收。
[翻译] 编写高性能 .NET 代码--第二章 GC -- 配置选项的更多相关文章
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少分配率, 最重要的规则,缩短对象的生命周期,减少对象层次的深度,减少对象之间的引用,避免钉住对象(Pinning)
		减少分配率 这个几乎不用解释,减少了内存的使用量,自然就减少GC回收时的压力,同时降低了内存碎片与CPU的使用量.你可以用一些方法来达到这一目的,但它可能会与其它设计相冲突. 你需要在设计对象时仔细检 ... 
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 避免使用终结器,避免大对象,避免复制缓冲区
		避免使用终结器 如果没有必要,是不需要实现一个终结器(Finalizer).终结器的代码主要是让GC回收非托管资源用.它会在GC完成标记对象为可回收后,放入一个终结器队列里,在由另外一个线程执行队列里 ... 
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 将长生命周期对象和大对象池化
		将长生命周期对象和大对象池化 请记住最开始说的原则:对象要么立即回收要么一直存在.它们要么在0代被回收,要么在2代里一直存在.有些对象本质是静态的,生命周期从它们被创建开始,到程序停止才会结束.其它对 ... 
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象
		减少大对象堆的碎片 如果不能完全避免大对象堆的分配,则要尽量避免碎片化. 对于LOH不小心就会有无限增长,但LOH使用的空闲列表机制可以减轻增长的影响.利用这个空闲列表,我们可以在两块分配区域中间找到 ... 
- [翻译]编写高性能 .NET 代码 第二章:垃圾回收
		返回目录 第二章:垃圾回收 垃圾回收是你开发工作中要了解的最重要的事情.它是造成性能问题里最显著的原因,但只要你保持持续的关注(代码审查,监控数据)就可以很快修复这些问题.我这里说的"显著的 ... 
- [翻译]编写高性能 .NET 代码 第二章:垃圾回收 基本操作
		返回目录 基本操作 垃圾回收的算法细节还在不断完善中,性能还会有进一步的提升.下文介绍的内容在不同的.NET版本里会略有不同,但大方向是不会有变动的. 在.net进程里会管理2个类型的内存堆:托管和非 ... 
- [翻译]编写高性能 .NET 代码  第一章:性能测试与工具 -- 平均值 vs 百分比
		<<返回目录 平均值 vs 百分比 在考虑要性能测试的目标值时,我们需要考虑用什么统计口径.大多数人都会首选平均值,但在大多数情况下,这个正确的,但你也应该适当的考虑百分数.但你有可用性的 ... 
- [翻译]编写高性能 .NET 代码 第一章:工具介绍 -- Visual Studio
		<<返回目录 Visual Studio vs虽然不是全宇宙唯一的IDE,但它是.net开发人员最常用的开发工具.它自带一个性能分析工具,你可以使用它来做开发,不同的vs版本在工具上会略有 ... 
- [翻译]编写高性能 .NET 代码 第一章:工具介绍 -- Performance Counters(性能计数器)
		<<返回目录 Performance Counters(性能计数器) 性能计数器是监视应用程序和系统性能的最简单的方法之一.它有几十个类别数百个计数器在,包括一些.net特有的计数器.要访 ... 
随机推荐
- 信号处理引发的cpu高
			背景知识: 1.tty 终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备. tty指的是七个alt+crtl+F1~F7.tty1-tty6表示文字界面,可以用Ctrl+Al ... 
- 读《你不知道的JavaScript(上卷)》后感-浅谈JavaScript作用域(一)
			原文 一. 序言 最近我在读一本书:<你不知道的JavaScript>,这书分为上中卷,内容非常丰富,认真细读,能学到非常多JavaScript的知识点,希望广大的前端同胞们,也入手看看这 ... 
- word中正文分栏重新换页问题
			小论文常需要正文分栏,但是标题.摘要不分栏的编排格式. 1.在摘要后面加入分隔符来将内容分为摘要和正文两个部分.选择 插入→分隔符→分节符(连续). 2.然后进行分栏.选择 格式→分栏. 3.此时如果 ... 
- Android 使用EventBus发送消息接收消息
			基本使用 自定义一个类 public class LoginEvent { private String code;//是否成功 public LoginEvent(String code) { th ... 
- 通俗易懂的分析如何用Python实现一只小爬虫,爬取拉勾网的职位信息
			源代码:https://github.com/nnngu/LagouSpider 效果预览 思路 1.首先我们打开拉勾网,并搜索"java",显示出来的职位信息就是我们的目标. 2 ... 
- 【转】CString,string,char*综合比较
			(一) 概述 1.string和CString均是字符串模a板类: 2.string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中: 3.CString(typedef CString ... 
- mysql基本了解
			数据库--MySql 数据仓库.就与我们之前学过的纯文本,properties这些技术一样.用来保存数据.并提供对数据进行增删改查的操作.我们以后做项目时,项目中的数据都是保存在数据库中的.//--- ... 
- 这可能是我觉得最折腾的C++环境配置(编码+调试)--mac+eclipse
			本着造福大众的心态,万一可能有人喜欢这种环境开发呢对吧~~折腾了一天,又是谷歌又是百度,讲真遇到报错问题搜出的资料挺少的,看来用这类环境开发C++的人不多,毕竟谁没事干放着xcode,vscode不用 ... 
- c# 对象 & 类
			类定义中可以使用的访问修饰符组合 none or internal 类只能在当前工程中访问 public 类可以在任何地方访问 abstract or internal abstract 类只能在当前 ... 
- 解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE
			问题 如下: 2017-07-16 08:50:57.436 INFO 13524 --- [ main] c.p.p.web.PointshopWebApplication ... 
