垃圾回收 (GC) 在 .NET Core 中是如何工作的?
提起GC大家肯定不陌生,但是让大家是说一下GC是怎么运行的,可能大多数人都不太清楚,这也很正常,因为GC这东西在.NET基本不用开发者关注,它是依靠程序自动判断来释放托管堆的,我们基本不需要主动调用Collect()释放内存,只需要注意对非托管资源进行及时释放就行。
虽说我们不用关注GC的运行,但是作为一个合格的程序员,还是有必要知道她是怎么工作的,因为垃圾回收对于一个程序来说真的太重要了,下面我们就用实际的应用来看下GC在.NET Core下是怎么工作的:
GC 会分配堆段,其中每个段都是一系列连续的内存。 置于堆中的对象归类为 3 个代系之一:0、1 或 2。 代系可确定 GC 尝试在应用不再引用的托管对象上释放内存的频率。 编号较低的代系会更加频繁地进行 GC。
对象会基于其生存期从一个代系移到另一个代系。 随着对象生存期延长,它们会移到较高代系。 如前所述,较高代系进行 GC 的频率较低。 短期生存的对象始终保留在第 0 代中。 例如,在 Web 请求存在期间引用的对象的生存期较短。 应用程序级别单一实例通常会迁移到第 2 代。
当 ASP.NET Core 应用启动时,GC 会:
- 为初始堆段保留一些内存。
- 在运行时加载时提交一小部分内存。
进行以上内存分配是出于性能方面的原因。 性能优势来自连续内存中的堆段。
GitHub 上提供了 MemoryLeak 示例应用。 MemoryLeak 应用:
运行起来是这样的
- Allocated:托管对象占用的内存量(当前系统认为要分配内存量)
- Working set:进程的虚拟地址空间中当前驻留在物理内存中的页集。 显示的工作集与任务管理器显示的值相同。(为当前进程分配的物理内存量)
- Gen 0:表示第0代堆段被回收
- Gen 1:表示第1代堆段被回收(同时回收0、1代)
- Gen 2:表示第2代堆段被回收(同时回收0、1、2代)
- RPS:每秒请求数
GC = Server asp.net 默认的是服务端GC
示例提供了很多接口用于调用测试
暂时性对象
我们先来看一下第一个接口:
[HttpGet("bigstring")]
public ActionResult<string> GetBigString()
{return new String('x', 10 * 1024);
}
创建一个 10-KB 字符串实例,并将它返回给客户端。 对于每个请求,会在内存中分配一个新对象并将它写入响应中。 字符串作为 UTF-16 字符存储在 .NET 中,因此每个字符都需要 2 字节内存。
使用压力测试工具Apache JMeter - Apache JMeter™
对这个接口进行压力测试,来观察内存使用情况
运行压力测试工具后可以看到内存使用及GC运行情况:
可以看到RPS在3K左右,当内存使用量升到了100M左右GC进行了第0代垃圾回收,第 0 代 GC 回收大约每两秒进行一次,内存消耗和释放(通过 GC)是稳定的,很少出现第1代回收,是因为分配的内存都是临时的小内存,并发量也在程序的可处理范围内,基本在第0代就可以完全回收。
持久性对象引用
接下来看下一个接口:
private static ConcurrentBag<string> _staticStrings = new ConcurrentBag<string>();[HttpGet("staticstring")]public ActionResult<string> GetStaticString(){var bigString = new String('x', 10 * 1024);_staticStrings.Add(bigString);return bigString;}
GC 无法释放上面的静态资源对象。 引用了不再需要的对象会导致内存泄露。 如果应用经常分配对象,但在不再需要对象之后未能释放它们,则内存使用量会随着时间推移而增加。
上面的 API 创建一个 10-KB 字符串实例,并将它返回给客户端。 与上一个示例的不同之处在于,此实例由静态成员引用,这意味着它不能被GC回收。
运行压力测试工具后可以看到内存使用及GC运行情况:
在上图中:
- 对
/api/staticstring进行压力
测试,会导致内存线性增加。 - GC 会在内存压力增加时,通过调用Collect来尝试释放内存,但是基本无济于事。
- GC 无法释放泄漏的内存。 已分配内存和工作集会随时间而增加。
停止压力测试后内存还在持续占用,手动调用Collect()也无济于事
我们只能调用Clear()来清理静态资源,然后Collect()进行回收
[HttpGet("clear")]public ActionResult<string> Clear(){_staticStrings.Clear();GC.Collect();GC.WaitForPendingFinalizers();GC.Collect();return "";}
本机内存
来看下一个接口:
[HttpGet("fileprovider")]
public void GetFileProvider()
{var fp = new PhysicalFileProvider(TempPath);fp.Watch("*.*");
}
某些 .NET Core 对象依赖于本机内存。 GC 无法回收本机内存。 使用本机内存的 .NET 对象必须使用本机代码进行释放。
.NET 提供了 IDisposable 接口,使开发人员能够释放本机内存。 即使未调用 Dispose,正确实现的类也会在终结器运行时调用 Dispose
。
PhysicalFileProvider 是托管类,因此任何实例在请求结束时都会被回收。
运行压力测试工具后可以看到内存使用及GC运行情况:
上面的图表显示此类的实现存在一个明显问题,它会不断增加内存使用量,这是因为忘记调用应释放的相关对象的 Dispose
方法
我改一下这个接口,使用using调用Dispose
:
private static readonly string TempPath = Path.GetTempPath();[HttpGet("fileprovider")]public void GetFileProvider(){using (var fp = new PhysicalFileProvider(TempPath)){fp.Watch("*.*");} }
可以看到内存得到了稳定的释放,GC调用也相对稳定
大型对象堆
频繁的内存分配/释放周期可能会导致内存碎片,尤其是在分配大型内存区块时。 对象在连续内存块中进行分配。 为了减少碎片,当 GC 释放内存时,它会尝试对其进行碎片整理。 此过程称为压缩。 压缩涉及移动对象。 移动大型对象会造成性能损失。 因此,GC 会为大型对象创建特殊内存区域,称为大型对象堆 (LOH)。 大于 85,000 字节(大约 83 KB)的对象:
- 置于 LOH 上。
- 不进行压缩。
- 在第 2 代 GC 期间进行回收。
当 LOH 已满时,GC 会触发第 2 代回收。 第 2 代回收:
- 在本质上速度较慢。
- 还会产生对所有其他代系触发回收的成本。
下面的代码会立即压缩 LOH:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
在使用 .NET Core 3.0 及更高版本的容器中,LOH 会自动压缩。
我们来看下一个api:
[HttpGet("loh/{size=85000}")]
public int GetLOH1(int size)
{return new byte[size].Length;
}
用压力测试工具调用 /api/loh/84975 这个接口
换一下对象大小 调用 /api/loh/84976 这个接口
比较上面两个图表
- 工作集对于这两种方案是相似的(大约 450 MB)。
- 低于 LOH 请求(84,975 字节)大部分显示第 0 代回收。
- 高于 LOH 请求(84,976 字节)生成恒定的第 2 代回收。 第 2 代回收成本高昂。 需要更多 CPU
84,976 字节会就触发了 85,000 限制
所以临时大型对象有性能问题,因为它们会导致第 2 代 GC。
为了获得最佳性能,应最大程度减少大型对象使用。 如果可能,请拆分大型对象。 例如,ASP.NET Core 中的响应缓存中间件会将缓存项拆分为小于 85,000 字节的块。
相关文章:

垃圾回收 (GC) 在 .NET Core 中是如何工作的?
提起GC大家肯定不陌生,但是让大家是说一下GC是怎么运行的,可能大多数人都不太清楚,这也很正常,因为GC这东西在.NET基本不用开发者关注,它是依靠程序自动判断来释放托管堆的,我们基本不需要主动调用Collect(…...

Appium 图像识别技术 OpenCV
在我们做App自动化测试的时候,会发现很多场景下元素没有id、content-desc、text等等属性,并且有可能也会碰到由于开发采用的是自定义View,View中的元素也无法识别到,很多的自动化测试框架对此类场景束手无策。Appium在V1.9.0中有给…...

产品Axure的元组件以及案例
前言 产品<Axure的安装以及组件介绍-CSDN博客经过上文我们可以知道我们Axure是一款适用于网站、移动应用和企业软件的交互式原型设计工具。它可以帮助用户创建高保真的交互式原型,包括线框图、流程图、模型、注释和规格等,以便与客户、开发人…...

智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.头脑风暴算法4.实验参数设定5.算法结果6.…...
flutter Pageview组件
PageView组件说明 组件说明PageView,PageController的源码简单demo 组件说明 属性说明scrollDirection滑动反向 Axis.vertical上下滑动 Axis.horizontal左右滑动reverse是否反转 true从最后一个记0controllerPageController见下文physics滚动方式pageSnapping是否有…...

如何用 Cargo 管理 Rust 工程系列 丙
以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/viSsCaFR2x9hZOvo1PoRqA 添加依赖项 前面已经提到过在 cargo 配置文件 Cargo.toml 中如何手动添加工程依赖项,cargo 同样提供了 add …...
Vue学习笔记-Vue3中的provide与inject
作用 provide和inject用于实现祖孙间的数据通信 用法 导入:import {provide,inject} from vue 使用: provide:祖组件使用该方法提供数据(可以给任意后代组件,但一般用于孙组件及其后代组件,因为父子间的…...

2021年数维杯国际大学生数学建模A题新冠肺炎背景下港口资源优化配置策略求解全过程文档及程序
2021年数维杯国际大学生数学建模 A题 新冠肺炎背景下港口资源优化配置策略 原题再现: 2020年初,新型冠状病毒(COVID-19)在全球迅速蔓延。根据世界卫生组织2021年7月31日的报告,新冠病毒疫情对人类的影响可能比原先预…...

【css】css实现文字两端对齐效果:
文章目录 一、方法1:二、方法2:三、注意: 一、方法1: 给元素设置 text-align: justify;text-align-last: justify;并且加上text-justify: distribute-all-line; 目的是兼容ie浏览器 p{width: 130px;text-align: justify;text-alig…...
ElasticSearch指南 - Mapping - Metadata fields
Metadatas - fields 每份doc都有关联它的metadata数据, 例如_index 和 _id字段. 这些metadatas字段的一些行为能在创建mapping的时候被定制化. 表示唯一性的metadatas字段 _index 表示doc属于哪个index _id doc的id 源doc的metadatas字段 _source doc的原始json字符串 _s…...
12.15每日一题(备战蓝桥杯摘花生)
12.15每日一题(备战蓝桥杯摘花生) 题目 摘花生 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。 地里每个道路的交叉点上都有种着一株花生苗,上…...

VUE-脚手架搭建
文章目录 一、概述二、前提准备1. 安装 node-js2. npm 镜像设置3. 安装 vs-code 三、脚手架搭建1. Vue-2 搭建1. Vue-3 搭建 一、概述 官网:http://cn.vuejs.org/ vue 有两个大版本,分别是 vue-2 和 vue-3,目前新项目的话用 vue-3 的会比较多…...
ArcGIS Pro SDK根据Xml/Json文件反向生成几何
需求: geometry文件导出后的xml,在另一台电脑上反向生成geometry 解决方案: 点 MapPoint minPointImport MapPointBuilderEx.FromXml(xml); 线 包络线 Envelope envelopeImport EnvelopeBuilderEx.FromXml(xml); 面 var geometryB…...
LY/T 3301-2022 实木厚芯胶合板检测
实木厚芯胶合板是指按照相邻层单板木纹方向垂直组坯,通过胶黏剂将表板、中间层板和芯板黏合而成的5层或5层以上的对称结构板材。 LY/T 3301-2022实木厚芯胶合板测试: 测试项目 测试方法 静曲强度 GB/T 17657 弹性模量 GB/T 17657 含水率 GB/T 17…...
代码随想录算法训练营第十六天| 104. 二叉树的最大深度、111. 二叉树的最小深度、222. 完全二叉树的节点个数
代码随想录算法训练营第十六天| 104. 二叉树的最大深度、111. 二叉树的最小深度、222. 完全二叉树的节点个数 题目 104.二叉树的最大深度 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 # Defin…...

字符串——OJ题
📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、字符串相加1、题目讲解2、思路讲解3、代码实现 二、仅仅反转字母1、题目讲解2、思路讲解3…...

Linux---cp和mv命令选项
1. cp命令选项 命令选项说明-i交互式提示-r递归拷贝目录及其内容-v显示拷贝后的路径描述-a保留文件的原有权限 cp -i命令选项效果图: cp -r命令选项效果图: cp -v命令选项效果图: cp -a命令选项效果图: -a选项说明: -a 选项还支持拷贝文件夹并且文件夹中的文件权限不丢失 …...

LVS负载均衡器(nat模式)+nginx(七层反向代理)+tomcat(多实例),实现负载均衡和动静分离
目录 前言 一、配置nfs共享存储 二、配置2个nginx节点服务的网页页面 节点1:192.168.20.10 步骤一:修改网关指向调度器的内网ip地址 步骤二:将nfs共享的目录进行挂载,并修改nginx的配置文件中location的root指向挂载点 步骤三ÿ…...

【深度学习】TensorFlow深度模型构建:训练一元线性回归模型
文章目录 1. 生成拟合数据集2. 构建线性回归模型数据流图3. 在Session中运行已构建的数据流图4. 输出拟合的线性回归模型5. TensorBoard神经网络数据流图可视化6. 完整代码 本文讲解: 以一元线性回归模型为例, 介绍如何使用TensorFlow 搭建模型 并通过会…...

智能插座是什么
智能插座 电工电气百科 文章目录 智能插座前言一、智能插座是什么二、智能插座的类别三、智能插座的原理总结 前言 智能插座的应用广泛,可以用于智能家居系统中的电器控制,也可以应用在办公室、商业场所和工业控制中,方便快捷地实现电器的远…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...