目前项目开发基本都基于.NetCore 3.1以上了,有些老版本的规则和概念也没有列出来,低版本的垃圾回收类型和内存释放方式会有所不同

垃圾回收器为什么存在

  • 开发人员不必手动释放内存。

  • 有效分配托管堆上的对象。

  • 回收不再使用的对象,清除它们的内存,并保留内存以用于将来分配。 托管对象会自动获取干净的内容来开始,因此,它们的构造函数不必对每个数据字段进行初始化。

  • 通过确保对象不能使用另一个对象的内容来提供内存安全。

托管堆代数

概述

为优化垃圾回收器的性能,将托管堆分为三代:第 0 代、第 1 代和第 2 代。目的是为了单独处理短生存期对象和长生存期对象。垃圾回收器大部分时间都在处理短生存期对象的回收。

底层一代的GC回收会触发年轻一代的GC回收,第二代的GC回收会触发完整的GC回收.

第0代(暂时代) 第1代(暂时代) 第2代 LOH(逻辑第3代)
所处内存段 暂时段 暂时段 非暂时段 非暂时段

LOH(大型对象堆)实际位于第二代
单独在第二代上为其划分了一块区域。
逻辑上称为第3代 |
| 包含 | 短生存期对象,即新分配的对象 | 短生存期对象,从第0代回收后,
未被回收的对象升级为第1代。 | 长生存期的对象,第一代回收后,
未被回收的对象升级为第2代。 | 对象的大小>= 85,000 字节 |
| 回收条件 | 第0代已分配内存达到阈值
如果第0代已满,仍尝试创建新对象
调用GC.Collect()方法
第1代GC回收 | 第1代已分配内存达到阈值
第0代回收之后仍然没有足够的空间存放新对象(此时会先回收第1代,再回收第2代)
调用GC.Collect方法
第2代GC回收 | 第2代已分配内存达到阈值
第0代回收之后仍然没有足够的空间存放新对象(此时会先回收第1代,再回收第2代)
调用GC.Collect方法
达到LOH回收条件
系统内存不足 | 达到第2代回收条件
大型对象内存分配达到阈值 |
| 回收方式 | 前台垃圾回收,当前托管线程被挂起 | 前台垃圾回收,当前托管线程被挂起 | 后台垃圾回收,当前托管线程正常执行 | 同第二代 |
| | | | | |

想要判断一个对象是否为大对象,可通过以下代码查看

var o = new Byte[85000];
Console.WriteLine(GC.GetGeneration(o));//GC2,大对象
o = new Byte[84900];
Console.WriteLine(GC.GetGeneration(o));  //GC0,小对象 84999仍是大对象,需要用一定量的内存空间保存指针
var arr = new int[85000 / 4];
Console.WriteLine(GC.GetGeneration(arr));//GC2,大对象,数组会提前开辟空间, int占32位,4个字节,85000 / 4加上指针内容会达到大对象的大小
arr = new int[85000 / 4 - 20];
Console.WriteLine(GC.GetGeneration(arr));//GC0,小对象

阈值

当垃圾回收器检测到某个代中的幸存率很高时,它会增加该代的分配阈值,避免垃圾回收过于频繁地运行

但是阈值调大之后,会导致一次回收的内存过高。

所以阈值由CLR动态决定,以调节 回收频率单次回收内存大小的平衡

垃圾回收类型

工作站(默认方式) 服务器
特点 垃圾回收线程同用户线程优先级相同,会与用户线程争用CPU资源
只有一个处理器的计算机无论是否修改配置文件最终都会应用工作站垃圾回收方式 有垃圾回收的专用线程

线程优先级为THREAD_PRIORITY_HIGHEST 每个CPU都会分配一个垃圾回收专用线程和专用堆。不同的堆可以互通
多个垃圾回收线程一起工作,所以堆大小相同时,服务器垃圾回收比工作站垃圾回收快 |
| 适用场景 | 普通场景 | 需要高吞吐量和可伸缩性的服务器应用程序 |

内存释放

释放目标

GC释放应用程序不再使用的对象的内存,通过检查应用程序的根来确定不再使用的对象应用程序的根包括:静态字段、局部变量、CPU 寄存器、GC 句柄和终结队列

释放步骤

- 列出不可访问对象和幸存对象的地址块并**标记**
- 使用内存复制功能压缩可以访问的对象到不可访问的地址块中,就是把存活下来的对象重新排列到连续的内存块中
- 大对象通常不会压缩,因为大对象所占用的内存区域过大,移动成本太大
- 回收死空间
- 指针更正,让对象指针指向新地址,指针更正是因为压缩了对象,对象在内存中的位置发生了变化

代码调优

  • 始终调用引用对象的Dispose方法,始终在实现了IDisposable的类中正确实现析构函数
  • 静态类中分配的对象不再使用后及时删除
  • 禁止在IOC声明为单例生命周期的类中注入瞬时生命周期的对象
  • 非必要时不要创建大型对象
  • 可视情况用ValueTask来代替Task,Task为引用类型,cpu密集型的调用会频繁触发第0代的GC回收
  • 尽可能重复使用HttpClient
  • 使用ArrayPoolMemoryPool从缓冲池中租用对象空间
  • 使用弱引用WeakReference重复使用已不再使用但尚未被回收的对象

监控及调试

  • 监听垃圾回收 ETW 事件,可用PerfView查看ETW事件,适用于window平台。也可在代码中引入Microsoft.Diagnostics.Tracing.TraceEventnuget包在代码中监听指定的GC回收等事件自定义后续处理逻辑

  • 使用性能监视器Perfmon.exe,适用于windows平台

  • 使用SOS调试,抓取dump转储文件后用WinDbg进行分析诊断,适用范围较广,可看到最全的内存信息

  • .Net CLI工具dotnet-counters,可以看到大概的性能指标数据统计结果,适用于临时运行状况查看和监视

.Net性能调优-垃圾回收!!!最全垃圾回收来了相关推荐

  1. jvm性能调优 - 13JVM的年轻代垃圾回收器ParNew原理

    文章目录 Pre GC回收器概述 最常用的新生代垃圾回收器:ParNew 如何为线上系统指定使用ParNew垃圾回收器? ParNew垃圾回收器默认情况下的线程数量 思考 面试题,parnew+cms ...

  2. jvm性能调优 - 15JVM的老年代垃圾回收器CMS的缺点

    文章目录 Pre 并发回收垃圾导致CPU资源紧张 Concurrent Mode Failure问题 内存碎片问题 什么情况下触发老年代GC Pre 上篇文章用一步一图的方式给大家讲清楚了CMS垃圾回 ...

  3. jvm性能调优 - 14JVM的老年代垃圾回收器CMS原理

    文章目录 Pre CMS垃圾回收的基本原理 如果Stop the World然后垃圾回收会如何? CMS如何实现系统一边工作的同时进行垃圾回收? 初始标记 并发标记 重新标记 并发清理 对CMS的垃圾 ...

  4. JVM内存模型和性能调优:JVM内存分配与回收:Minor GC后存活的对象Survivor区放不下- 第26篇

    Minor GC后存活的对象Survivor区放不下,这种情况会把存活的对象部分挪到老年代,部分可能还会放在Survivor区. (1)当我们的代码中有allocation1和allocation2 ...

  5. “金三银四”春招指南之“性能调优”:MySQL+Tomcat+JVM,看完还怕面试官的轰炸?

    春招指南之"性能调优":MySQL+Tomcat+JVM,还怕面试官的轰炸? 01 MySQL性能调优 1.1 MySQL性能调优问题有哪些?怎么学? 关于这个,给大家看一份学习大 ...

  6. mysql dba工作笔记pdf_社区专家在线:Oracle数据库、MySQL、Db2 等数据库日常运维故障与性能调优在线答疑...

    数据库的重要性毋庸置疑,随着数据量日益增加,数据库的重要性更为凸显.DBA们作为数据库的日程运维管理人员,肩负着数据库运维的重要使命.一名合格的DBA,日常工作中需要掌握多项技能,包括数据库的故障诊断 ...

  7. Android性能调优篇之探索垃圾回收机制

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  8. Java5.0垃圾回收性能调优-1、简介,2、Ergonomics工效学[Vange译]

    Introduction 简介 The JavaTM 2 Platform Standard Edition (J2SETM platform) is used for a wide variety ...

  9. 性能测试分析与性能调优诊断--史上最全的服务器性能分析监控调优篇

    来源: https://www.cnblogs.com/laoqing/p/11629941.html 一个系统或者网站在功能开发完成后一般最终都需要部署到服务器上运行,那么服务器的性能监控和分析就显 ...

  10. gateway 内存溢出问题_带你学习jvm java虚拟机 arthas/性能调优/故障排除/gc回收/内存溢出等...

    学完本课程,您将掌握: 内存溢出问题实战 CPU飙升问题实战 阿里巴巴Arthas在线诊断 Class字节详细拆解 手写类加载器.四种类加载器.双亲委托模型 对象创建.存储.访问.加载解析 性能调优. ...

最新文章

  1. C++ std::function<void(int)> 和 std::function<void()> 作为函数参数的注意事项
  2. Redis Lua脚本中学教程(下)
  3. html表单上传图片获取路径,asp.net获取HTML表单File中的路径的方法
  4. oracle 11.2.0.5下载,oracle 11.2.0.4和10.2.0.5下载地址
  5. dialogue怎么读_法语助手|法汉-汉法词典 dialogue是什么意思_dialogue的中文解释和发音_dialogue的翻译_dialogue怎么读...
  6. python qq模块_常用的Python模块
  7. 岁月在变迁,彼此在成长。而我在流浪
  8. mysql中engine是什么意思_mysql中engine=innodb和engine=myisam的区别
  9. C语言#define预处理
  10. js 跳转传递汉字参数
  11. 软件需求规格说明书模板(Spec)
  12. maya2011安装方法图文详细教程及Unity下载
  13. 20天学会UI设计(PS+AI)入门教程
  14. 有点先生和差不多女士
  15. 阿里云ECS主机部署LAMP环境
  16. 图片工具picpick
  17. 使用IDEA制作Java面向对象小游戏《原谅帽大作战》
  18. java 开发微型公众账号应用
  19. Linux 系统故障排查
  20. 【观察】戴尔VxRail 8:无缝衔接VMware新技术,重塑下一代超融合系统

热门文章

  1. C#并行编程(6):线程同步面面观
  2. ASP.NET Core 2.0使用Autofac实现IOC依赖注入竟然能如此的优雅简便
  3. winserver的consul部署实践与.net core客户端使用(附demo源码)
  4. 如果你也会C#,那不妨了解下F#(5):模块、与C#互相调用
  5. Visual Studio “15”第三个预览版发布
  6. .NET Core VS Code 环境配置
  7. Web服务器 - Nginx配置介绍
  8. SQL查询的安全方案
  9. 【BIM入门实战】Revit入门基础知识选择题带答案解析(116题)
  10. 完美解决ArcGIS10.x栅格空间插值报错无法进行和导出插值栅格结果出错的问题