前言
.NET 占的内存大吗?大,非常大,不过也正是一种正常的现象。
10几年前我就用 VS2008 开发软件,那会的软件运行在 XP 系统上,也没有感觉占用内存大,不过到了后来,随着VS 版本的升级,功能的强大,编译出来的软件越来越大,运行系统也从XP 一路升级,win7、win10、win11,采购的成本、配置也越来越高,系统运行慢的声音也是越来越大,没办法我们一边优化软件,一边升级电脑的配置。
接下来我们就来,我们就详细的拆解一下这个问题。
一、.NET内存管理架构分析
.Net 占用内存大的核心原因是:分代 GC 管理机制、托管堆的预分配、JIT 编译换成以及运行时元素存储等。
1、CLR 运行时内存开销
JIT 编译器缓存,大约占内存 200M,用于存储编译后的机器码。
元数据存储,包括类型信息,反射数据以及数据集元数据等相关信息。
运行时服务,包括线程池、同步、一次性处理等机制。
2、分代垃圾回收机制
分代 GC 的内存回收机制的
垃圾回收器将堆上的内存分为了三代。
刚刚分配的对象位于第0代,在第一轮回收中存活的对象为第1代,而其他所有对象为第2代。
第0代和第1代对象就是所谓的短生存期(ephemeral)的代。CLR将第0代控制在一个相对较小的空间内(典型大小在几百KB至几MB)。当第0代填满时,GC就会触发第0代垃圾回收。第0代垃圾回收会频繁发生。
GC对第1代内存应用了相似空间限制(作为第2代的缓冲区),且第1代内存的回收也相对快速而频繁。一次完整的内存回收会包含第2代内存。
3、典型的 .NET 应用约占 1.2 G 内存左右
其中:CLR 运行时占 200M、托管堆 600M、大对象 250M、其他组件 150M。
二、其他技术占内存使用情况
| 技术栈 | 典型内存约占(M) | 主要组成 | 优势 | 劣势 |
|---|---|---|---|---|
| .Net | 1200 | CLR + 托管堆 + LOH + 其他 | 开发效率高、内存安全 | 内存开销大 |
| Java | 1300 | JVM + 堆 + 元空间 + 其他 | 生态成熟 | 启动慢、内存开销大 |
| C++ | 80 | 程序代码 + 堆栈 + 其他 | 性能好、内存可控 | 开发复杂、易出错 |
| Node.js | 200 | V8引擎 + 堆 + 其他 | 开发快速、生态丰富 | 单线程 |
| Python | 400 | 解释器 + 对象 + 模块 | 简单易学、库丰富 | 性能较低 |
三、.NET 内存优化策略
1、对象生命周期管理
使用 using 语句管理资源
using (var fileStream = new FileStream("data.txt", FileMode.Open))
using (var reader = new StreamReader(fileStream))
{
// 自动释放资源,即使发生异常
return reader.ReadToEnd();
}
2)对象池模式实现
2、数据结构优化
避免使用大对象
3、GC 配置优化
项目文件配置
运行时 GC 调优
4、字符串优化策略
字符串驻留优化
其实, .NET 应用占用内存大是有道理,因为 .NET 提高了开发效率相比 C++ 而言,开发效率提高了很多倍,而且动态内存管理避免了大量的潜在 Bug。现在单片成本不高,相比 .NET 占的这点内存优势不要太明显,你说呢?
关键词
.NET、内存占用、GC、CLR、JIT、对象池、字符串优化、托管堆、内存管理、运行时
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!
作者:全小鱼
出处:zhihu.com/question/662756682/answer/1942177727990994219
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!