秘境探索之一个.NET 对象从内存分配到内存回收

前方高能预警,新手慎入!不听劝阻者,轻则郁闷堆积,重则生死看淡,对编程失去了念想,对生活失去了幻想!好了,心理强大到NB的可以忽略前方若干警示。为了探索.NET对象的内存分配和回收销毁,您可能需要准备一些调试的基本知识,比如上篇的<利用SOS扩展库进入高阶.NET6程序的调试>.以下例子来自.net 6技术支持。

1. 我们的第一个对象

我们的第一个对象,不是你初中暗恋的古灵精怪的小女孩,更不是你高中的神秘御姐范的初恋女友,她是地地道道的Object。

不信,我Show给你看。

public static int Main()
{MaoniType o = new MaoniType(128, 256);Console.ReadLine();// 其它乱七八糟的代码return 0;
}

掀开她神秘的盖头,她也只不是千千万万普通对象中的一员,非要说她有什么不同的话,那可能就是你想驯服她,并且你花费了你的宝贵时间,在她身上。

public class MaoniType
{public MaoniType(int a, int b){A = a;B = b;}public int A { get; set; }public int B { get; set; }
}

2. 正确的打开她

美丽总是隐藏在朦胧之中,隔纱看美人,越看越迷人。

不过我们需要的不是肤浅的撩骚,让我们利用高级窥探工具,更加深入到灵魂的探索她。

当然,最最简单的探索工具,就是Windbg + SoS 扩展了。

至于工具的使用,不是重点,在这里就略过了,如果你还不会的话,那么就移步<利用SOS扩展库进入高阶.NET6程序的调试>瞧瞧,那里已经给你备好了下酒好菜。

闲话少叙,让我们直接打开工具,键入神秘指令,来个一指入魂吧。

0:007> .load C:\Users\webmote.dotnet\sos\sos.dll
0:007> !dumpheap -stat
Statistics:MT    Count    TotalSize Class Name
00007ffc77c37598        1           24 System.IO.SyncTextReader
00007ffc77c33478        1           24 System.Threading.Tasks.Task+<>c
00007ffc77c1ca70        1           24 System.IO.Stream+NullStream
00007ffc77c13798        1           24 ConsoleApp6.MaoniType
...
[omitted]00007ffc77bd7f48       28         1160 System.SByte[]
00007ffc77bd8410        4         3596 System.Int32[]
00007ffc77c1d3c8        3         4178 System.Byte[]
00007ffc77b2b578        8        18216 System.Object[]
00007ffc77c33898        3        33356 System.Char[]
00007ffc77bdd698       82        35610 System.String
Total 208 objects

没错,找到 ConsoleApp6.MaoniType 这个类名,这就是你心心念的 对象 No 1.

3. 深入内存

既然已经被你定位到了,那么就让我们继续深入吧, 现在只需要点她的牌牌就可以了。

0:007> !DumpHeap /d -mt 00007ffc77c13798Address               MT     Size
000002470000c0c8 00007ffc77c13798       24     Statistics:MT    Count    TotalSize Class Name
00007ffc77c13798        1           24 ConsoleApp6.MaoniType
Total 1 objects

现在,有了她第一手的资讯:

姓名:Maoni/莫妮
尺寸:24
起点:c0c8 [000002470000c0c8]
个数:1个
表索引:[00007ffc77c13798]

4. 继续深入——内存布局调查

让我们来看看GC地址空间的情况:

0:007> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000024700001030
generation 1 starts at 0x0000024700001018
generation 2 starts at 0x0000024700001000
ephemeral segment allocation context: nonesegment             begin         allocated         committed    allocated size    committed size
0000024700000000  0000024700001000  00000247000173C8  0000024700022000  0x163c8(91080)  0x21000(135168)
Large object heap starts at 0x0000024710001000segment             begin         allocated         committed    allocated size    committed size
0000024710000000  0000024710001000  0000024710001018  0000024710002000  0x18(24)  0x1000(4096)
Pinned object heap starts at 0x0000024718001000
0000024718000000  0000024718001000  0000024718005420  0000024718012000  0x4420(17440)  0x11000(69632)
Total Allocated Size:              Size: 0x1a800 (108544) bytes.
Total Committed Size:              Size: 0x22000 (139264) bytes.
------------------------------
GC Allocated Heap Size:    Size: 0x1a800 (108544) bytes.
GC Committed Heap Size:    Size: 0x22000 (139264) bytes.

你应该没忘记我们对象的地址吧?

莫妮的地址是 000002470000c0c8,而新生段的分配信息我们也可以清晰的看到。

当然有关,估计仍然需要一大章节才能说明白吧,这里仅仅简单介绍下。

它是GC从操作系统采集内存的一个单位,实际内存申请和分配以及释放以segment(段)为单位;

例如: workstation GC模式segment大小为16M,server GC模式segment大小为64M。

Gen 0Gen 1 heap总是位于同一个段中,叫做ephemeral segment(新生段),
Gen 2 heap由0个或多个segments组成,LOH由1个或多个segments组成

.NET程序启动时CLR为heap创建2个segment,一个作为ephemeral segment,另一个用于LOH

Full GC后完全空闲的segments将被释放掉,内存返回给操作系统

再次深入前,让我们来点小甜点,放松一下,看看四周的风景。

4.1 我们怎么用DRAM

不管怎么分配,我们都需要涉及到物理内存。

当然,我们并不支持使用物理内存!

我们使用虚拟内存(VM),这块有操作系统的哦VMM(虚拟内存管理器)提供。

操作系统引入了虚拟内存概念,使得我们能够:

  • 每个进程都认为它有自己的内存空间,就好象国家的廉租房制度一样,让每个人都体验到家的温馨。

  • 你可以请求更多的内存,甚至超过了物理内存大小,而管理器只会占用真正使用的物理内存;

  • 重要的是,不需要VM分配为连续的了,实现了即抛即用。

VM的实现也很有意思,由操作系统提供页的支持:

  • 由MMU(内存管理单元)实现

  • 内存被分割为页(一般是4K)

  • 虚拟内存到物理内存由页映射使用页表进行管理

  • 无法映射到物理内存,会导致页失败错误

  • 操作系统控制页映射转换

有很多技术实现更快的转换,比如页表缓存、TLB(Translation Lookaside Buffer)技术等。

75cc77f10cb2c87c83b2c8d51bbdc02b.png

4.2 物理页是怎么组织的?

8b3f209ad5634f7632750547152e378f.png

  1. 当计算机启动后,Windows操作系统把来自DRAM的物理页整理为一个列表;

  2. 当有进程需要物理页分配时,它转变为WS(Working Set)的一部分

  3. 当一个物理页从WS移除后,它通过软件页故障或硬页故障返回到列表

  4. 硬页故障是非常耗时的,因此我们需要避免它
    5.为了避免硬页故障,我们不能增加大于物理内存的堆栈(可以观察物理内存负载信息)

4.3 GC怎么从VM采集内存

  • 保留内存

    由于需要分页的原因,因此我们可以请求稍后可能使用的范围地址,它被称作保留内存(VirtualAlloc 使用 MEM_RESERVE)。当然保留内存不能保存任何数据。

  • 提交内存

    当我们需要在页存储上存储数据时,我们告诉操作系统,这叫提交内存。(VirtualAlloc使用MEM_COMMIT),提交操作成功后,保证你不会得到OOM异常。

保留内存操作是非常快的,当然你仍然需要增加一次用户态<–> 内核态的操作;提交内存也是非常快的… 当然,知道你真正的保存数据。而恰恰这个时候,有可能引起分配页故障,导致OOM。

  • 保存数据
    一切都oK了,我们呢就可以轻松保存数据了。

5. 再次深入内存布局调查

让我们回到从前,一如第一次初见。

5.1 初见

3e754a6b49edbcd292d45971a3b6fdef.png

假设上图就是我们的段(segment)内存的保留内存(Reserve memory)区域,那么你想到了什么?

是的,首先她是一个空荡荡的巨大空间!

当然,这里面也没有任何东西。

5.2 相识

现在,我们想要在段内存中保存一些东东,该怎么办呢?

3857f1d6072308de817cda22755e4773.png

是的,我们得混个脸熟!

好了,首先我们需要保存段的头信息,那让我们先提交个申请(通常是64K)。

有了第一次后,我们对这个操作流程应该熟门熟路了,所以,谁也抵挡不住我们前进的脚步。

e443466ab061258e4fc7c5ec1b8fcd18.png

再次提交存储对象的空间请求(通常是64K),当然,GC通常不会仅仅为一个对象申请内存.

5.3 行动

它通常先申请一个分配上下文,当然这个时候并没有对象被构造。

c0fad67d9d2e7e71ac824c48dbd9abc6.png

然后动用物理内存页,保存数据,查看存储信息如下:

0:007> dq 000002470000c0c8-8 l3
00000247`0000c0c0  00000000`00000000 00007ffc`77c13798
00000247`0000c0d0  00000100`00000080

其内部大致的流程如下(精简版):

344de9d5c33b912625f8f6481cf5d296.png

注意:缓存是非常快的,以下是来自Intel的数据。

  • L1 缓存:4 cpu周期

  • L2 缓存:12 cpu周期

  • L3 缓存:44 cpu周期

DRAM的读取大约 60ns ~ 100ns之间。

5.4 小结下

经过前面不断的深入探索,对象的内存分布已经在你面前完全展开。那么,让我们再总结下。

ec99470491fa544b279831f0f2f01a46.png

GC的分配如下:

b103f1d7aa940f1208fe51e448c902a6.png

6. 清扫战场

经过上面让人目眩神秘的命令和图片,你学废了吗?

最后,让我们打扫下战场,看看GC这位小宝贝。

94e84d5f6f1ae444ce8c5cf2800e1b96.png

6.1 GC怎么决定收集

如下代码,让我们看看它能有多智能?

public static int Main()
{MaoniType o = new MaoniType(128, 256);GCHandle h = GCHandle.Alloc(o, GCHandleType.Weak);GC.Collect();Console.WriteLine("Collect called, h.Target is {0}",(h.Target == null) ? "collected" : "not collected");return 0;
}

发生了什么?输出是:

Output - Collect called, h.Target is not collected

是的,你没有看错,GC.Collect()收集整个堆栈,这意味着GC不能决定对象的生命周期。
如果一个对象还活着,那么GC会被告知,在这个例子中,JIT(User Roots)告诉GC,对象还活着。因此GC无法回收对象。

6.2 开始收集

好了,让我们来个真正的回收。

[MethodImpl(MethodImplOptions.NoInlining)]public static void TestLifeTime(){MaoniType o = new MaoniType(128, 256);h = GCHandle.Alloc(o, GCHandleType.Weak);}public static int Main(){TestLifeTime();GC.Collect();Console.WriteLine("Collect called, h.Target is {0}",(h.Target == null) ? "collected" : "not collected");return 0;}

输出结果:

Output: Collect called, h.Target is collected

再次观察GC:

7961b3913c5e7b9adbd8ac66abdadb17.png

是的,GC摧毁了对象,内存回收了。

7089f06a094ff89cacb09bf23c8b55b8.png

7. 小结

经过本次的多次深入刨析,你对你的对象是不是更加了解了?

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?

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

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

相关文章

这五部关于宇宙的神级纪录片,带你探索未知的外太空世界

宇宙之大无奇不有&#xff0c;在你的认知里你又知道多少关于宇宙的事情&#xff0c;如果单单用外星人概括你所对宇宙的认知就真的太片面了&#xff0c;小编今天就带来下面这四部关于宇宙的硬核纪录片&#xff0c;带你真正的去了解关于宇宙的知识&#xff0c;让你遨游在宇宙的知…

Exceptionless服务端+kibana部署实时日志纪要

安装软件列表Exceptionless.4.1.2861.zipelasticsearch-5.6.14.zipkibana-5.6.14-windows-x86.zip安装准备1. 在D盘下创建Exceptionless文件夹2. 拷贝需要安装的软件(参照上面安装软件列表)到Exceptionless文件夹下3. 安装JDK 1.8 (C环境中已经有安装, 步骤忽略)4. …

好心帮男朋友洗衣服,他却要分手??

1 每天一个分手小技巧&#xff08;via.平民窟公主&#xff09;▼2 导航最近的加油站&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 单位停电发的蜡烛&#xff08;via.蜻蜓队长&#xff09;▼4 我也不知道原来有人这样穿啊&#xff01;&#xff08;素材来源网络&…

Android之如何解决右上角不显示3个点的菜单

之前写过小例子,发现菜单栏右上角的那3个点老是显示不出来,今天终于解决了,不废话,先爆照。 我之前的代码menu_main.xml 文件如下 <menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools&quo…

大型网站架构系列:电商网站架构案例

为什么80%的码农都做不了架构师&#xff1f;>>> #0 系列目录# 大型分布式网站架构大型分布式网站架构技术总结大型网站架构系列&#xff1a;电商网站架构案例#1 电商案例原因# 分布式大型网站&#xff0c;目前看主要有几类1.大型门户&#xff0c;比如网易&#xff…

八、结构模式之组合(Composite)模式

组合模式属于对象的结构模式&#xff0c;有时又叫做部分-整体模式&#xff0c;组合模式将对象组织到树结构中&#xff0c;可以用来描述整体与部分的联系。其可以使客户端将单纯元素和组合元素同等对待。 当需求中是体现部分与整体层次的结构时&#xff0c;以及你希望用户可以忽…

代言男科、站台微商、变身神棍....这些科学家被捧了几十年,黑历史曝光后,让人三观尽毁......

全世界只有3.14 % 的人关注了爆炸吧知识说到诺贝尔奖得主&#xff0c;尤其科学类奖项&#xff0c;吃瓜群众的感受常常是:不明觉厉。关于他们有多牛x的故事&#xff0c;你肯定听了不少。但你一定很少听过&#xff0c;诺奖得主转而研究伪科学&#xff0c;或者为了恰饭疯狂掉节操的…

拉屎能赚钱?在马桶上月入过万?原来卫生间里还有这么多隐藏福利,超模君都惊了……

全世界只有3.14 % 的人关注了爆炸吧知识模友们&#xff0c;你们有过“带薪拉屎”的经历吗&#xff1f;没错&#xff0c;假如我们每天花10分钟“带薪拉屎”&#xff0c;那一年大概能积攒下来40小时&#xff0c;假如我们每天工作8小时&#xff0c;等于多了5天年假&#xff0c;白嫖…

Android之让图片匀速旋转效果

图片匀速旋转 当我们更新的时候,需要把更新小图标旋转起来,不废话,先爆照 介绍动画: Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果;第二类是 Frame 动画,即顺序播放事先…

dotnet 使用 Infer# 自动分析代码缺陷

本文告诉大家如何使用 Infer# 开源库配合 GitHub 的 Action 实现自动分析代码缺陷&#xff0c;如找到可空引用或线程安全等问题这是一个在 GitHub 上完全开源的仓库&#xff0c;请看 https://github.com/microsoft/infersharp刚好今天收到了 Infer# 发布 1.2 版本博客&#xff…

发了篇paper,双非二本的她直博浙大

全世界只有3.14 % 的人关注了爆炸吧知识大家好&#xff0c;我是小南&#xff0c;本科就读于国内某双非二本院校&#xff0c;于2019年拿到了浙江大学的直博录取函。很多人问我从二本院校成功跨越到国内知名高校的秘诀是什么&#xff0c;我个人觉得&#xff0c;除开运气&#xff…

PS网页设计教程XVI——在PS中创建一个摩登实验室风格的网页设计

作为编码者&#xff0c;美工基础是偏弱的。我们可以参考一些成熟的网页PS教程&#xff0c;提高自身的设计能力。套用一句话&#xff0c;“熟读唐诗三百首&#xff0c;不会作诗也会吟”。 本系列的教程来源于网上的PS教程&#xff0c;都是国外的&#xff0c;全英文的。本人尝试翻…

好评率超高的9个公众号,值得收藏

不管世界变化多快&#xff0c;阅读仍是个不过时的动作。今天就为大家推荐几个优质公众号&#xff0c;从社会热点、读书成长、生活新知&#xff0c;你的碎片化时间&#xff0c;我们包了&#xff01;一起来看看呀~长按二维码&#xff0c;“识别图中二维码”即可订阅————电商头…

.NET 6新特性试用 | 文件范围的命名空间

前言在前面的《隐式using指令》文章中&#xff0c;我们介绍了global using&#xff0c;可以减少我们代码文件中的“噪音”&#xff0c;使代码更简洁。今天&#xff0c;我们介绍.NET 6中另一个简化代码的方式——文件范围的命名空间。Demo当我们向项目中添加一个类文件时&#x…

Android之三大图片缓存原理、特性对比

一. 四大图片缓存基本信息 Universal ImageLoader 是很早开源的图片缓存&#xff0c;在早期被很多应用使用。Picasso 是 Square 开源的项目&#xff0c;且他的主导者是 JakeWharton&#xff0c;所以广为人知。Glide 是 Google 员工的开源项目&#xff0c;被一些 Google App 使用…

他读博期间连发3篇Science,28岁任武大教授后再发Nature!

全世界只有3.14 % 的人关注了爆炸吧知识来源&#xff1a;募格课堂整合自武汉大学、武汉晚报、半月谈等有这样一位学者&#xff0c;读博期间以一作身份发表3篇Science,28岁成为武汉大学化学与分子科学学院教授再发2篇Nature&#xff0c;35岁荣获杰青......今年9月&#xff0c;他…

Android 页面布局xd,Adobe XD强大的布局系列工具 助你事半功倍

数字设计有多种形式-从移动端、桌面网站到显示屏应用程序、智能助手、车载娱乐系统(例如CarPlay和Android Auto)等等。为当今的应用程序打造数字体验意味着需要针对各种屏幕尺寸、布局和交互类型进行设计。作为设计师&#xff0c;您的时间应该花在用户体验上&#xff0c;而不是…

如果觉得午休时间太短怎么办?

1 假装自己戴了口罩&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 正义不会迟到博主是男的&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 阅读理解有多难&#xff1f;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 下雨天就不要爬树了&…

WPF 实现温度计

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织在WPF中没有现成的温度计控件&#xff0c;所以我们自己实现一个。微信群人数太多入群请添加小编微信号&#xff08;yanjinhuawechat&#xff09;或&#xff08;W_Feng_aiQ&#xff09;邀请入群&am…

100-6

2019独角兽企业重金招聘Python工程师标准>>> /**\第6题&#xff08;数组&#xff09;腾讯面试题&#xff1a; 给你10分钟时间&#xff0c;根据上排给出十个数&#xff0c;在其下排填出对应的十个数 要求下排每个数都是先前上排那十个数在下排出现的次数。 上排的十个…