编写高性能 .NET 代码 第二章:垃圾回收

垃圾回收是你开发工作中要了解的最重要的事情。它是造成性能问题里最显著的原因,但只要你保持持续的关注(代码审查,监控数据)就可以很快修复这些问题。我这里说的“显著的原因”,实际上是我们对垃圾回收的理解和期望不正确导致的。在.NET开发中,内存的性能问题和CPU的性能问题一样多,这就是单独开一章主要描述这个问题的原因。

当我们提及垃圾回收造成的开销时,就会不如自主的紧张起来,但一旦你理解它,就能很好的优化你的程序。在后面文章里,你可以看到GC可以在大多数情况下,在堆处理上提供很好的性能,同时也能很好解决内存分配与内存碎片问题。

Windows在非托管堆里用使用一个空闲列表来维护内存分配。尽管它会想尽办法来减少内存碎片,但很多长时间运行的非托管代码(本地代码)的程序还是会碰上内存碎片问题。它会花很多时间在空闲列表里找到合适可分配地址。随着内存使用持续增长,不可避免的需要不断重启来解问题。一些程序还会采用自定义内存分配的方案(自己的内存分配算法来接管malloc)函数来解决内存碎片问题。

.NET里的内存分配通常在一个内存段里进行,这样申请和回收的消耗会小很多。托管堆通过将最近申请的内存对象放在一起,可以减少对空闲列表的遍历,提升性能。

在默认的分配过程中,通过代码获得对象的大小,然后在剩余的缓冲区里分配它。因为没有竞争,只要有合适的空间就能很快的分配。一旦这要申请的空间这一段无法满足,GC分配器会创建一个新的内存段,在这上面开始分配,之后的新的分配也都会在这新创建的内存段里进行。

这个过程中系统代码(分配器)只会做一些简单的检查。

我们来看一个简单的栗子:

private class MyObject{    
private int x;  
 private int y;    
 private int z; }
 
 private static void Main(string[] args){  
   var x = new MyObject(); }

首先,我们在分配器前设置一个断点

; Copy method table pointer for the class into; 
ecx as argument to new() ; You can use !dumpmt to examine this value. mov ecx,3F3838h; Call newcall 003e2100;
Copy return value (address of object) into a register mov edi,eax

目前分配的是:

; NOTE: Most code addresses removed for formatting reasons.
;
; Set eax to value 0x14, the size of the object to; allocate, which comes from the method table
mov eax,dword ptr [ecx+4] ds:002b:003f383c=00000014; Put allocation buffer information into edx
mov edx,dword ptr fs:[0E30h]; edx+40 contains the address of the next available byte; for allocation. Add that value to the desired size.
add eax,dword ptr [edx+40h]; Compare the intended allocation against the
; end of the allocation buffer.
cmp eax,dword ptr [edx+44h]; If we spill over the allocation buffer,
; jump to the slow path
ja 003e211b; update the pointer to the next free
; byte (0x14 bytes past old value)
mov dword ptr [edx+40h],eax; Subtract the object size from the pointer to; get to the start of the new objsub eax,dword ptr [ecx+4]; Put the method table pointer into the
; first 4 bytes of the object.
; eax now points to new objectmov dword ptr [eax],ecx; Return to caller
ret; Slow Path – call into CLR method003e211b jmp clr!JIT_New (71763534)

总之,这些涉及到方法调用的指令只有9个,不是很难懂。
如果你使用了一些配置选项,例如工作站模式,它不会因为竞争而导致分配变慢,因为GC给每一个处理器(cpu内核)分配了一个堆(段)。.NET在这些内存分配地方做了一些复杂处理,但你不必深入了解它是如何工作,只需要知道如何优化它就可以了。

我在本书开头就涉及到垃圾回收是因为今后章节里很多东西都会涉及到它。正确的理解垃圾回收是帮助你实现好性能的基础。

相关文章:

  • [翻译]编写高性能 .NET 代码 第一章:性能测试与工具 -- 选择什么来衡量

  • [翻译]编写高性能 .NET 代码 第一章:性能测试与工具 -- 平均值 vs 百分比

  • [翻译]编写高性能 .NET 代码 第一章:工具介绍 -- Visual Studio

  • 编写高性能 .NET 代码 第一章:工具介绍 -- Performance Counters(性能计数器)

原文地址:http://www.cnblogs.com/yahle/p/6550044.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/325249.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中判断一个字符在字符串中出现的次数

源代码: //java中判断一个字符出现的次数//在下面字符串中查找有几个啊public static void testFindChar(){String str "啊!我爱你中国!啊,我爱你故乡";//存放每个字符的数组String [] strs new String[str.length()…

深入浅出 Java 中的包装类

转载自 深入浅出 Java 中的包装类 前阵子,我们分享了《Java中的基本数据类型转换》这篇文章,对许多粉丝还是有带来帮助的,今天讲一下 Java 包装类的的由来,及自动装箱、拆箱的概念和原理。 什么是包装类型 Java 设计当初就提…

java中实现将一个数字字符串转换成逗号分隔的数字串, 即从右边开始每三个数字用逗号分隔

源代码如下: /*将一个数字字符串转换成逗号分隔的数字串,即从右边开始每三个数字用逗号分隔 */public static void testFenGeNumber(){String number "1235954";StringBuffer sb new StringBuffer(number);for(int i number.length()-3;i&g…

事件总线(Event Bus)知多少

1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉。事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖&…

影响程序员生涯的三个错误观念,你千万不要犯

转载自 影响程序员生涯的三个错误观念,你千万不要犯 程序员在社会上,到底是怎样一个生活群体?是否能找到自己方向?其实,路一直都在那里,只是你看不到而已! 当初的你,可能一直被一…

用 docker secrets 保存 appsettings.Production.json

这是我们使用阿里云容器服务基于 docker 容器部署 asp.net core 应用遇到的另一个问题 —— 如果将包含敏感信息的应用配置文件 appsettings.Production.json 传递给运行在容器中的 asp.net core 应用。 Docker 针对这样的应用场景已经提供了解决方案 —— Docker Secrets&…

人脸识别简要说明

近日,或许是毕业季来临,或许是研究人脸识别的同行增多。总之,通过博客找我的人可所谓“络绎不绝”。 这几年来,自己不断的抽些碎片时间,整理出来的人脸识别各个版本,于2017年9月26日发布的java的第一个版本…

读《代码不朽:编写可维护软件的10大要则》C# 版

这本书特别针对没有接受过计算机科学或软件工程专业学习的软件开发人员,这类人员除了熟悉所用语言语法和语义之外,很少接受其他专业培训,对软件工程中的一些概念理解欠缺。软件设计方面考虑较少。如果要成为一个专业的程序员,就需…

mysql多表查询的分类

内连接 等值连接 非等值连接 自连接 外连接 inner join 等值连接 非等值连接 自连接 外连接

再有人问你volatile是什么,把这篇文章也发给他(深入分析)

转载自 再有人问你volatile是什么,把这篇文章也发给他 在上一篇文章中,我们围绕volatile关键字做了很多阐述,主要介绍了volatile的用法、原理以及特性。在上一篇文章中,我提到过:volatile只能保证可见性和有序性&…

Cockroach DB 1.0发布

分布式SQL数据库Cockroach DB遵循软件产品以动物命名的模式。近日,该数据库的第一个生产就绪版本1.0发布。 许多人将Cockroach DB视为Google Spanner的开源版本。后者是一个强一致性、横向可扩展的RDBMS,它起初是一个服务于谷歌服务的内部项目&#xff…

分享10道常考Java面试题及答案

转载自 分享10道常考Java面试题及答案 Hi&#xff0c;大家好&#xff0c;今天给大家分享10道常考的Java面试题及答案&#xff0c;涉及到Java中的10个方面。每个领域一道题。希望你能有收获。 <面向对象>什么是面向对象&#xff1f;什么是面向过程&#xff1f;面型对象…

对数据进行插入操作并且获取主键的值

eg. eg:工作中写定时模块&#xff0c;先插入时间段&#xff0c;然后直接获取id

编写高性能 .NET 代码 第二章:垃圾回收 基本操作

基本操作 垃圾回收的算法细节还在不断完善中&#xff0c;性能还会有进一步的提升。下文介绍的内容在不同的.NET版本里会略有不同&#xff0c;但大方向是不会有变动的。 在.net进程里会管理2个类型的内存堆&#xff1a;托管和非托管。本地代码申请的&#xff0c;以及由CLR申请…

如何设计一个高可用的运营系统

转载自 如何设计一个高可用的运营系统 这是一篇来自粉丝的投稿&#xff0c;作者【林湾村龙猫】近一年在做关于运营活动方面的设计。本文是他的关于运营活动的总结&#xff0c;Hollis做了一点点修改。 概述 一个产品业务的发展总是离不开运营二字。随着业务快速的发展以及新…

.Net中的AOP系列之《AOP实现类型》

本系列的实验环境&#xff1a;VS 2017。 读完本章后&#xff0c;可能仍然不能实现自己的AOP工具&#xff0c;但应该对两种主要类型&#xff08;PostSharp和Castle DynamicProxy&#xff09;的AOP工具的运行原理有了基本的理解。PostSharp是一个在编译时编织的后期编译器&#x…