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

推荐订阅源

月光博客
月光博客
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
InfoQ
N
Netflix TechBlog - Medium
D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
SegmentFault 最新的问题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
C
Cisco Blogs
T
Threat Research - Cisco Blogs
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园_首页
Recorded Future
Recorded Future
J
Java Code Geeks
The Cloudflare Blog
S
Securelist
人人都是产品经理
人人都是产品经理
T
Tor Project blog
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
V
Vulnerabilities – Threatpost
V
V2EX
P
Palo Alto Networks Blog
I
Intezer
罗磊的独立博客
博客园 - 叶小钗
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Hacker News
The Hacker News
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
P
Privacy International News Feed
P
Proofpoint News Feed
美团技术团队
Cisco Talos Blog
Cisco Talos Blog
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
L
LINUX DO - 热门话题
Simon Willison's Weblog
Simon Willison's Weblog
MyScale Blog
MyScale Blog
H
Help Net Security
W
WeLiveSecurity
Google Online Security Blog
Google Online Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

博客园 - Ring

运行Java cmd程序 找不到或无法加载主类怎么解决 Generics and Collection (2) Generics and Collection (1) mybatis, spring, springmvc 什么时候该用NoSQL? 如何学习Javascript 好文章尽收眼底 事务和锁 索引 VS调试Javascript. Asp.net常用状态管理方案分析 .NET中的缓存知识总结 "The server has rejected the client credentials"解决方案 - Ring 有关IIS7概述以及配置和开发的几篇文章摘录 CodeForFun--编写自动登录Email的程序 是什么使得我的进程崩溃了? OutOfMemory这家伙是谁?为什么我还留有许多内存,它却使进程崩溃了? ASP.NET 崩溃-SiteMap中疯狂的循环 何时.NET中AppDomain会回收?
.NET如何使用内存---餐馆案例分析
Ring · 2006-09-21 · via 博客园 - Ring

        前几天工作中,我听到我的一个同事正给一位客户解释有关内存的使用和为什么会出现内存异常的问题。虽然我在早期的一篇文章中谈到了内存溢出和内存管理,但我觉得他的分析实在太有趣了,因此我想将此也分享给大家。   

         声明: 为了避免冗长,我简化许多东西。譬如,我是这么说的,垃圾回收器分配64MB区段空间。尽管在不同的framework版本下分配的区段空间大小是不同的。并且跟最初给各个对象分配的空间有关,譬如,读取大对象堆。另外的一些有关内存分配细节依赖于配置,我在这也不考虑这些细节了。 

第一部分 -通常的内存使用

         若你读过我先前的贴子,就会知道:32位系统进程典型寻址空间为2GB的虚拟地址空间。这是供给工作的内存空间,它独立于同时占有多少RAM空间。占有更多的RAM有益于提升性能,但它并不会帮助扩展到2GB之外的地址空间。

         此时,你将这2GB的地址空间想象成餐馆的所有占地空间。

         你为对象(不管受否是.net对象)分配空间时,通常两步走:先预定空间,然后将对象置于预定的空间内。

         内存预定工作如同在餐馆中预定餐桌。正如餐馆一样,内存预定依赖其内存管理器(memory manager),他会帮你预定到一块连续的内存(memory in chunks)。譬如,你有一个3人的聚会,餐馆里很可能没有3人餐桌,但你可能会预定一个4人餐桌,你就会使用其中的3个座位,浪费一个座位。

         相对于内存空间,你预定餐桌好比预定内存(这块内存现占用虚拟字节),实际占用的座位(3个座位)好比实际占用内存(实际占用的内存占用私有字节)。没有预定的地板空间就是剩余可用内存。

         一个美好的晚上,餐馆的情景可能这样:

         蓝色区域表示已经预订的空间红色区域表示实际使用的空间,白色区域表示剩余的可用空间。如下图所示:
        

         现在假如某人某人电话预订一个3人餐桌,他将被告之餐馆已无可用餐桌。因为3个人坐在一起需要一个4人餐桌。尽管可以分在两个2人餐桌上坐下,但这似乎并不是一个好主意,因为你们想坐在一起。
         
         相似地,内存预定也不可能将内存分成小块,分散在各个不同的地方。要不就是什么也不分配,要不就是在一块连续的区域内分配。因此内存预定也如上面的预定3人餐桌情景,那么将会“内存溢出”,尽管还有足够的小块剩余空间可用。

         细心的观众也许会说,不是可以将各个餐桌靠陇,使他们一个连着一个,这不是腾出一个4人餐桌出来了吗?但是已经用餐的客户愿意此时移动餐桌吗?预定内存正如这样。

         我们谈论了内存碎片,也谈了剩余但不可用的内存块(因为他们太小了,不足以容纳一个新的餐桌),并且我们也谈谈有多少已经预订了但尚未使用的内存(这不同于占用虚拟字节和私有字节的内存)。
 
第二部分 -.NET的垃圾回收

         绝大多数情况下,你依靠某种内存管理器(memery manager)(譬如,NT Heap, C++ Heap,GC等等)在应用程序中创建对象。在餐馆案例情景下,你将内存管理器比作女服务员,她会为你预定座位并会带你到相应的座位上。例如,调用了malloc方法,就不需要提供欲分配到的地址,而只需告之需要的内存区块大小,malloc会返回内存预定的地址。ok,在“C++ heap"区的table 1就是安置给你的地址。

         .NET的垃圾回收机制(GC) 则要更进一步。进程中,若要想使用.net对象,它会预先保留一张大“桌子”(64座的桌子)。当某人创建了.net对象,GC会接待他们到桌子的下一个可用座位。有时接待员也会在餐桌旁来回走动,检查是否有人已经用餐完毕并邀请他们离开,此时其他的客人会就坐该餐桌。一些人可能需要等待其他人用餐完毕才能离开(比如引用对象),因此他们必须呆着等待。也有一些"大爷"人物(钉扣对象[pinned objects]),占据着靠窗的座位,很生气地说,“我不走了”。这就意味着,他不能腾出位置来,其他人也过不来。

         客人和客人间留着的空位好比.NET内存碎片。

         一旦64座的桌子坐满了,如需接待新来客人,GC需要预定一个新的64座的桌子。如果预定失败,就会抛出一个内存溢出异常。

但是,它的真正面目怎样?

好了, 分析得足够透了,在这儿你将看到真正的asp.net应用程序内存情况。

         再次说明一下,红色部分表示已使用内存,篮色部分表示预定但尚未使用的内存,白色部分表示剩余可用内存。

        在内存空间的末端,你看到的一些小点很可能是一些动态链接库。如同餐馆情形下,尽管还有很多的白色空间,很可能在两个红点间的空隙不足以容纳一个64 M的区块,在下一次GC申请一块新的内存时,就会产生一个内存溢出异常。

        这些小红点(动态链接库)像这样布满整个空间的原因是由于这些特殊的动态链接库会装载在更适合的基地址上。你不能对那类动态链接库预先分配地址,因为很难预测他们将分配的更适合的地址在哪,对此你仅能做的是,找出实际使用的内存到底去哪了。