惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
NISL@THU
NISL@THU
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
宝玉的分享
宝玉的分享
Cisco Talos Blog
Cisco Talos Blog
Help Net Security
Help Net Security
月光博客
月光博客
V
V2EX
量子位
T
Threat Research - Cisco Blogs
A
About on SuperTechFans
Google DeepMind News
Google DeepMind News
Google DeepMind News
Google DeepMind News
P
Privacy International News Feed
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
Arctic Wolf
S
Schneier on Security
H
Hacker News: Front Page
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cisco Blogs
G
GRAHAM CLULEY
The Cloudflare Blog
博客园 - Franky
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
云风的 BLOG
云风的 BLOG
H
Heimdal Security Blog
The GitHub Blog
The GitHub Blog
C
Check Point Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Blog of Author Tim Ferriss
小众软件
小众软件
Hacker News: Ask HN
Hacker News: Ask HN
T
Tenable Blog
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
T
Troy Hunt's Blog
B
Blog
Blog — PlanetScale
Blog — PlanetScale
腾讯CDC

博客园 - Ansel

如何做到某个网站被访问? 也谈项目经理 项目团队几个发展阶段总结 如何当好一个项目经理(引用) 微创面试归来话感想 二分法——查找、排序以及库函数bsearch的用法 关于web.config - Ansel - 博客园 使用C#和MSMQ开发消息处理程序 访问数据库时如何解决并发问题 very nice to have talked with you via phone 压缩ASP.NET中的ViewState 利用程序动态管理Web.config文件 使用ASP.NET Global.asax 文件--基础篇 ASP.NET 2.0 的内部变化 .Net调用Java的WebService之亲身体验 服务器端异步 Web 方法 在 ASP.NET 中支持数据库缓存相关性 关于 .NET Passport 身份验证 用.Net开发Windows服务初探
.NET框架垃圾回收机制
Ansel · 2006-08-03 · via 博客园 - Ansel
 

.NET框架垃圾回收机制

    .NET框架包含一个托管堆,所有的.NET语言在分配引用类型对象时都要使用它。像值类型这样的轻量级对象始终分配在栈中,但是所有的类实例和数组都被生成在一个内存池中,这个内存池就是托管堆。

   .NET框架中的垃圾回收器被称为分代的垃圾回收器(Generational Garbage Collector),也就是说被分配的对象划分为3个类别,或称为“代”。分别为012012代对应的托管堆的初始化大小分别是256K2M10M。垃圾回收器在发现改变大小能够提高性能的话,会改变托管堆的大小。例如当应用程序初始化了许多小的对象,并且这些对象会被很快回收的话,垃圾回收器就会将第0代的托管堆变为128K,并且提高回收的频率。如果情况相反,垃圾回收器发现在第0代的托管堆中不能回收很多空间时,就会增加托管堆的大小。在应用程序初始化的之前,所有等级的托管堆都是空的。当对象被初始化的时候,他们会按照初始化的先后顺序被放入第0代的托管堆中。 

    最近被分配内存空间的对象被放置于第0代,因为第0代很小,小到足以放进处理器的二级(L2)缓存,所以第0代能够为我们提供对其中对象的快速存取。经过一轮垃圾回收后,仍然保留在第0代中的对象被移进第1代中,再经过一轮垃圾内存回收后,仍然保留在第1代中的对象则被移进第2代中。第2代包含了生存期较长的对象,这些对象至少经过了两轮回收。

    C#程序为一个对象分配内存时,托管堆几乎可以立即返回新对象所需的内存,托管堆之所以能有这样高效的内存分配性能是由于托管堆较为简单的数据结构。托管堆类似于简单的字节数组,有一个指向第一个可用内存空间的指针。

    在某块被某对象所请求时,上述指针值就会返回给调用函数,而指针会重新调整至指向下一个可用的内存空间。分配一个托管内存块只比递增一个指针的值稍微复杂一点。这也是托管堆所优化的性能之一。在一个不需太多垃圾回收的应用程序中,托管堆的表现会优于传统的堆。

    由于这个线性的内存分配方法的存在,在C#应用程序中同时分配的对象在托管堆上通常会被分配成彼此相邻。着安排和传统的堆内存分配完全不同,传统的堆内存分配是基于内存块大小的。例如,两个同时分配的对象在堆上的位置可能相距很远,从而降低了缓存的性能。因此虽然内存分配很快,但在一些比较重要的程序中,第0代中的可用内存很有可能会彻底被消耗光。记住,第0代小到可以装进L2缓冲区,并且没有被使用的内存不会被自动释放。当第0代中没有可以分配的有效内存时,就会在第0代中触发一轮垃圾回收,在这轮垃圾回收中将删除所有不再被引用的对象,并将当前正在使用中的对象移至第1代。针对第0代的垃圾回收是最常见的回收类型,而且速度很快。在第0代的垃圾内存回收不能有效的请求到充足的内存时,就启动第1代的垃圾内存回收。第2代的垃圾内存回收要作为最后一种手段而使用,当且仅当第1代和第0代的垃圾内存回收不能被提供足够内存时进行。如果各代都进行了垃圾回收后仍没有可用的内存,就会引发一个OutOfMemeryException异常 。