通俗易懂话GC-C#的内存管理

news2025/7/10 9:27:17

昨天和一个朋友聊到图像处理软件内存占用多的问题,然后很自然聊到了GC,回想起以往很初学者都问到类似的问题:

1、C#自己就会垃圾回收,为什么我还要关心垃圾回收?

2、GC可以回收垃圾,但回收的时候又会让线程卡住,我到底该不该GC.Collect()?

为了回答这些问题,我们先从一个小实验讲起

我们先做这样一个程序,不断从电脑摄像头读取图像,然后显示出来,代码很简单:

using OpenCvSharp;

using var capture = new VideoCapture(0, VideoCaptureAPIs.DSHOW);
if (!capture.IsOpened())
    return;

capture.FrameWidth = 1920;
capture.FrameHeight = 1280;
capture.AutoFocus = true;

const int sleepTime = 10;

using var window = new Window("capture");


while (true)
{
    var image = new Mat();
    capture.Read(image);
    if (image.Empty())
        break;

    window.ShowImage(image);
    int c = Cv2.WaitKey(sleepTime);
    if (c >= 0)
    {
        break;
    }
}

你将看到,内存持续增长,直到发生GC,如此往复:

 现在我们加入手动GC:


using OpenCvSharp;

using var capture = new VideoCapture(0, VideoCaptureAPIs.DSHOW);
if (!capture.IsOpened())
    return;

capture.FrameWidth = 1920;
capture.FrameHeight = 1280;
capture.AutoFocus = true;

const int sleepTime = 10;

using var window = new Window("capture");


while (true)
{
    var image = new Mat();
    capture.Read(image);
    if (image.Empty())
        break;

    window.ShowImage(image);
    int c = Cv2.WaitKey(sleepTime);
   //手动触发GC
     GC.Collect();
    if (c >= 0)
    {
        break;
    }
}

可以看到,随着密集的GC,内存占用平稳了:

但是,问题解决了吗?有经验的小伙伴会知道,GC会让程序变卡,所以手动GC在大多数时间并不是一个万能灵药,相反是毒药,那么真正的解决方案是什么呢?

我们把代码再改一下:

把GC.Collect(); 改成 image.Dispose();


using OpenCvSharp;

using var capture = new VideoCapture(0, VideoCaptureAPIs.DSHOW);
if (!capture.IsOpened())
    return;

capture.FrameWidth = 1920;
capture.FrameHeight = 1280;
capture.AutoFocus = true;

const int sleepTime = 10;

using var window = new Window("capture");


while (true)
{
    var image = new Mat();
    capture.Read(image);
    if (image.Empty())
        break;

    window.ShowImage(image);
    int c = Cv2.WaitKey(sleepTime);
   // GC.Collect();    //手动触发GC
   image.Dispose();   //手动释放对象
    if (c >= 0)
    {
        break;
    }
}

可以看到,即没有发生内存暴涨,也没有发生GC。

为什么呢?GC.Collect(); 和 image.Dispose(); 分别发生了什么?

GC.Collect(); 时,程序内部发生了大迁徙:

第一步 GC线程会把其它线程从合作模式转换到抢占模式,合作模式线程可以访问托管堆和非托管堆,抢占模式只能访问非托管堆,可以简单的认为,GC线程会暂停其它线程。

第二步 把托管堆的对象都标记为垃圾(我不是针对谁)。

第三步 标记出存活的对象。

第四步 清理失活对象,把标记存活的对像向前移动,覆盖空闲内存区,在后部空出整片的空闲区。

第五步 恢复其它线程。

image.Dispose();时,程序只是把imgae对象所占的区域标定为空闲区。成本是极低的。

GC的成本很高,我应该想办法避免GC,尤其是在程序需要高实时响应的场合,那么又有了新的问题:

能避免自动GC吗?

首先,不需要过分担心自动GC,因为它和手动GC的“成本”大多数情况下并不相同。

为了不动辄进行大迁徙,设计者有设计分代回收的优化策略,一般对象初始化时会放在0代,每经历一次GC还能存活,就会上升一代,最终来到2代。大对象(大于85,000 byte) 比如图像初始化时就在2代。0代和1代的空间比较小,这样也是为了加速GC,自动GC一般不会像手动GC那样,把所有的代都整一遍,而是会优先回收低代内存,如果不够才会回收高代。

但避免自动GC还是我们的终极目标,想避免自动GC,首先要明白,自动GC什么时候会发生?

1、给新对象分配空间时,发现不够了。

2、收到系统物理内存不够的通知。

所以,总结一下:

1、大对象要手动销毁。别人实现的.Dispose()的要记得调用,自己写的大对象类要实现.Dispose()。

2、力大砖飞,物理内存要够大。

3、在合适的时候手动GC。

4、避免频繁创建大对象,比如上面的代码最优应该是下面这样:


using OpenCvSharp;

using var capture = new VideoCapture(0, VideoCaptureAPIs.DSHOW);
if (!capture.IsOpened())
    return;

capture.FrameWidth = 1920;
capture.FrameHeight = 1280;
capture.AutoFocus = true;

const int sleepTime = 10;

using var window = new Window("capture");

//在循环外创建大对象
using var image = new Mat();

while (true)
{
    
    capture.Read(image);
    if (image.Empty())
        break;

    window.ShowImage(image);
    int c = Cv2.WaitKey(sleepTime);
 
    if (c >= 0)
    {
        break;
    }
}

 

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

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

相关文章

js深浅拷贝:保证赋值后改变第二个变量的值,不影响第一个变量的值

对于基本数据来说,将一个变量赋值给另一个变量,第二个变量值改变了,不会影响第一个变量;但对于复杂类型中的对象来讲,将一个对象赋值给另外一个对象,其实是将放对象内容的地址赋值给了第二个对象&#xff0…

Amazon EKS绑定alb 使用aws-load-balancer-controller(Ingress Controller)对外提供服务

1、创建AWS Load Balancer Controller 的 IAM 策略 亚马逊相关文档 下载地址 打开 策略 点击 创建策略 打开 IAM_Policy.json 复制内容粘贴到 json 点击下一步:标签 然后一直下一步 在下图中名称填写 AWSLoadBalancerControllerIAMPolicy 你也可以自定义名称。然后创建策略。…

尚医通_第11章_医院排班管理和搭建用户系统环境

尚医通_第11章_医院排班管理和搭建用户系统环境 文章目录尚医通_第11章_医院排班管理和搭建用户系统环境第一节、-医院排班管理需求分析一、医院排班管理需求1、页面效果2、接口分析第二节、医院排班管理-科室列表一、科室列表(接口)1、添加service接口和…

李峋同款爱心代码

李峋爱心代码背景代码运行pycharm打包成exe程序背景 最近大火的电视剧《点燃我温暖你》出现,令我的家庭地位进一步下降,因为男主“李峋”已经变成了她的大老公,而我就被打入冷宫. 为了满足她的“攀比心”,我连夜给她实现了粉红色爱…

第十节:多态【java】

目录 🍀1.多态 📖1.1 多态的概念 📒1.2 多态实现条件 👆1.2.1向上转型 💯1.2.2重写 🔱1.2.3动态绑定和静态绑定 🌈1.2.4多态的应用 👇1.2.5向下转型 📕1.3多态的…

Java岗面试核心NIO有关知识总结

这篇文章主要是阅读了一些关于NIO的文章,对一些重要的部分进行了摘取总结。BIO、NIO、AIO的不同 BIO:同步阻塞IO模式,线程发起IO请求后,一直阻塞IO,直到缓冲区数据就绪后,再进行下一步操作。NIO&#xff1a…

SpringCloud基础知识【Hystrix熔断器】

SpringCloud基础知识【Hystrix熔断器】1. Hystrix概述2. Hystix-隔离2.1 线程池隔离2.2 信号量隔离2.3 Hystix隔离小结3. Hystix-降级3.1 服务提供方降级3.2 消费方降级3.3 Hystix降级小结4. Hystix-熔断4.1 代码演示4.1 熔断监控5. Hystix-限流1. Hystrix概述 Hystix&#xf…

基于概率距离削减法、蒙特卡洛削减法的风光场景不确定性削减(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

一文带你吃透数据库的约束,不做CRUD程序员

在SQL标准中,一共规定了6种不同的约束,包括非空约束,唯一约束和检查约束等,而在MySQL中是不支持检查约束的,所以这篇文章先对其余5种约束做一个详解和练习。 文章目录1. 约束的概念2. 约束的分类3. 非空约束4. 唯一约束…

.net 大型物流综合管理网络平台源码【免费分享】

淘源码:国内专业的免费源码下载平台 源码分享,需要源码学习可私信我! 一、源码描述 这是一款大型的物流综合管理网络平台源码,十分完整实用,便于调试,涵盖了物流综合管理的全面内容,该源码运行比…

单商户商城系统功能拆解30—营销中心—积分签到

单商户商城系统,也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法,例如拼团,秒杀,砍价,包邮…

【负荷预测】基于改进灰狼算法(IGWO)优化的LSSVM进行负荷预测(Matlab代码实现)

📝个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,…

IDEA 中Git 多次 Commit 合并为一次提交

一、背景 由于个人习惯的原因,喜欢一个功能分多次提交,导致很多提交比较零碎。 有时候经常需要将零碎的提交合并成一次,该怎么办? 可以使用 IDEA 自带的 Git 插件 将多次 Commit 合并成一次。 二、问题描述 如希望将第二次到第…

新品上市 | “电子表格软件”轻装上阵,企业报表用户的新选择

2022年11月14日,恰逢思迈特软件11周年的生日,我们更新了电子表格软件(Smartbi Spreadsheet),希望在一站式BI产品之外,更多的企业用户可以通过成熟、可控、小巧、灵活的报表工具,提升数据化管理的…

分击合进,锦江之星酒店与白玉兰酒店再领投资热潮

2022年11月11日,「山水画中游,暇享好时光」品牌品鉴会在广西桂林隆重召开。锦江酒店(中国区)旗下两大酒店品牌锦江之星酒店和白玉兰酒店携手亮相本次活动。 (品牌矩阵品鉴会活动现场) 后疫情时代&#xff…

JDBC编程的基本流程

文章目录1、创建数据源2、让代码和数据源建立连接3、操作数据库3.1 插入操作3.2 删除操作3.3 修改操作3.4 查找操作1、创建数据源 创建DataSource对象,这个对象描述了数据库服务器在哪,需要导入包javax.sql.DataSource DataSource databases new Mysq…

【第006篇】通过impdp命令导入dmp文件到Oracle11g数据库中

准备:按照dmp文件的账号密码,如 gwpc/gwpc 创建好表空间、用户等信息。 1、执行以下命令获取DATA_PUMP_DIR的值。 select * from dba_directories;2、将上图圈主的那个路径复制出来备用:/opt/oracle/app/admin/orcl/dpdump/ 3、将dmp文件放…

3.35 OrCAD中怎么产生Cadence Allegro的第一方网表?OrCAD软件输出Cadence Allegro第一方网表报错时应该怎么处理?

笔者电子信息专业硕士毕业,获得过多次电子设计大赛、大学生智能车、数学建模国奖,现就职于南京某半导体芯片公司,从事硬件研发,电路设计研究。对于学电子的小伙伴,深知入门的不易,特开次博客交流分享经验&a…

从0开始搭建ELK日志收集系统

Elasticsearch elasticsearch是一个高度可扩展全文搜索和分析引擎,基于Apache Lucene 构建,能对大容量的数据进行接近实时的存储、搜索和分析操作,可以处理大规模日志数据,比如Nginx、Tomcat、系统日志等功能。 Logstash 数据收…

一周侃 | 周末随笔

前言 明天又是周一了,感慨时间过得真快,2022年只差一个月就要过去了。大家年初定的目标实现了吗【狗头】 作为一个技术类博主,我平常除了看专业书籍和论文之外,很喜欢看一些闲书,比如时政类、经济类、历史人文类、科…