重学c#系列——c# 托管和非托管资源与代码相关(四)
前言
这是续第三节。
概况垃圾回收与我们写代码的关系:
- 强引用和弱引用
- 针对共享 Web 承载优化
- 垃圾回收和性能
- 应用程序域资源监视
正文
强引用和弱引用
垃圾回收器不能回收仍在引用的对象的内存——这是一个强引用。它可以回收不在根表中直接或间接的托管内存。然而,有时可能会忘记释放内存。
注意:如果对象相互引用,但是没有在根表中引用,例如:对象A 引用对象B,B引用C,C引用A,这时候如果ABC没有在根表中引用那么直接会被销毁。
补充一下根表在垃圾回收中的作用:
垃圾回收在引用的根表中找到所有引用对象,接着在引用的对象树中查找。
恰恰正好弱类型就没有在根表中,然后垃圾处理器首先开刀的就是弱类型引用。可以这么理解,理论上弱引用关联的对象只能生存到下一次垃圾收集发生为止,但是往往不会那么短时间,因为垃圾收集器并不是那么容易发现这些弱引用。
强引用很好理解:
如果应用程序的代码可以访问一个正由该程序使用的对象,垃圾回收器就不能回收该对象, 那么,就认为应用程序对该对象具有强引用。
var student=new Student();
一但student离开了所在作用区域那么引用对象就开始要被销毁了。
所以我们有缓存这个概念:
var myCache=new MyCache();
myCache.add(student);
缓存的本质目的不就是为了延长垃圾回收吗?或者说不让其垃圾回收,持续在内存中。当student 超出作用区后,还是不能释放student 的引用内存,因为此时对象在缓存对象中引用。
即使是student=null后,那么这个时候new Student()还是在内存中,因为被缓存对象引用了,student在栈中的指向(无论是清空回收还是置空)控制不了释放垃圾回收了。
那么能不能这样,即使被myCache引用了还是可以自动被消耗?这个时候就是弱类型登场的时候。
官方文档这样介绍道:
弱引用允许应用程序访问对象,同时也允许垃圾回收器收集相应的对象。
如果不存在强引用,则弱引用的有限期只限于收集对象前的一个不确定的时间段。
使用弱引用时,应用程序仍可对该对象进行强引用,这样做可防止该对象被收集。
但始终存在这样的风险:垃圾回收器在重新建立强引用之前先处理该对象。
占用大量内存,但通过垃圾回收功能回收以后很容易重新创建的对象特别适合使用弱引用。
假设 Windows 窗体应用中的树状视图向用户显示层次结构复杂的选项。 如果基础数据量很大,则用户使用应用程序中的其他部分时,在内存中保留该树会导致效率低下。
这里有些关键的地方,一个体现就是:数据量很大,也就是弱类型适合占有内存比较大的对象。为什么这样说呢?
是这样子的,我们创造一个弱类型就是要内存开销的,本身目的就是为了及时回收降低内存,这个时候整弱类型这不是添堵吗?
第二个在于容易创建,如果不容易创建,那么这个时候是空间换时间的代价有点大啊。
如何延长弱类型的生命周期呢?这时候应该使用七星灯[强类型]进行续命。
举个栗子:
var myWeaKReference=new WeakReference(new DataObject());
if(myWeaKReference.isAlive)
{
DataObject strongReference=myWeaKReference.Target as DataObject;
}
这时候吧弱类型给了一个强类型引用。
起码可以续命到if结束,也就不用担心用到一半的时候突然挂了,那么就非常尴尬。
垃圾回收和性能
垃圾回收机制和影响到性能,最简单的例子就是垃圾回收不好,导致了内存过大。
那么我们就需要去排除是不是垃圾回收的问题。
首先第一步要确定是否是垃圾回收问题,可能出现下面的问题:
1. 引发内存不足异常
2. 进程占用过多内存
3. 垃圾回收器回收对象的速度不够快
4. 托管堆太零碎
5. 垃圾回收暂停时间太长
6. 第 0 代太大
7. 垃圾回收期间的 CPU 使用率太高
那么如何去排除呢?这时候就要使用工具了。
举个容易出现的例子:托管堆太零碎,这与我们代码息息相关。
我们代码可能会出现,下面的情况:
频繁加载和卸载许多小的程序集。
与非托管代码互操作时,保留了太多对 COM 对象的引用。
大型暂时性对象的创建会导致大型对象堆频繁分配和释放堆段。
这些会导致托管堆太零碎。
如何去排查?
这时候可以使用windbg,这个工具还是很好用的。最主要是windows10现在自带了,没有版本不够升级一下,对了不会windows 10还用盗版吧?
我们都是正经人,能白嫖肯定白嫖啊,不给钱就不算嫖啊。
下面是我调试的内容:
可能有些人没用过windbg,简单过下流程。
打开windbg后:
选择对应的进程,进程很多,那么这个时候你应该打印出来。如果调试打包好的,直接看程序名。
Console.WriteLine(Process.GetCurrentProcess().Id);
然后开始调试。
你需要加载sos,来查看托管程序。
.net core 加载是这样子的.load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.8\sos
然后查看一下是否加载完毕: !help.
然后你就可以查询一些托管的东西。
在这里!dumpheap -type Free -stat 显示堆里面的一些使用情况,上图windbg就是了。
若要确定第 0 代中的可用空间,请键入以下命令以获取代的内存使用信息:
!eeheap -gc
当然这是一个漫长查看过程,但是想要高性能,这又是必须的。
针对共享 Web 承载优化
我直接把文档里面的贴过来吧,因为这很详细了。
由于垃圾回收器保留内存以供将来分配,因此它提交的空间可能会超过真正所需。 可以减少此空间来适应系统内存负载过重的情况。 减少提交的此空间可提升性能,并将容量扩展为托管更多网站。
如果启用 gcTrimCommitOnLowMemory 设置,垃圾回收器会计算系统内存负载,并在负载达到 90% 时进入修整模式。 除非负载下降到不到 85%,否则会一直处于修整模式。
如果条件允许,垃圾回收器可以决定 gcTrimCommitOnLowMemory 设置对当前应用没有帮助并忽略它。
然后给了一个示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<runtime>
. . .
<gcTrimCommitOnLowMemory enabled="true"/>
</runtime>
. . .
</configuration>
应用程序域资源监视
这个是什么呢?就是说用来监控应用域监视cpu和内存的使用情况。里面是这样解释的,说多个应用在服务器上运行,可以监听到哪个程序占用过多,同时告诉我们这个arm消耗小。
这个呢,其实个人觉得现在容器化了,监控容器专门的工具了,很容易监听到。
有四种启动资源监控的东西。
1.可以在 CLR 启动时启用 ARM,具体操作是向配置文件添加 <appDomainResourceMonitoring> 元素,并将 enabled 属性设置为 true。 值 false(默认值)只表示不在启动时启用 ARM;稍后可以使用其他激活机制之一来激活它。
2.主机可以请求获取 ICLRAppDomainResourceMonitor 托管接口来启用 ARM。 成功获取此接口后,就会启用 ARM。
3.托管代码可以将静态 AppDomain.MonitoringIsEnabled 属性(Visual Basic 中的 Shared)设置为 true,从而启用 ARM。 设置此属性后,就会启用 ARM。
4.启动后,可以通过侦听 ETW 事件来启用 ARM。 使用 AppDomainResourceManagementKeyword 关键字启用公共提供程序 Microsoft-Windows-DotNETRuntime 后,ARM 便会启用,并开始抛出所有应用域的事件。 若要将数据与应用域及线程相关联,还必须使用 ThreadingKeyword 关键字启用 Microsoft-Windows-DotNETRuntimeRundown 提供程序。
首先改配置文件的放弃。然后 Windows 事件跟踪 (ETW)是windows的。去调用api感觉麻烦。应用程序域资源监视非常重要,但是还是找个第三方监听吧。
结
前面一直介绍托管资源,后面介绍非托管资源,整理了一点点。
注:上述纯属个人的整理,如有误,望指出。
重学c#系列——c# 托管和非托管资源与代码相关(四)的更多相关文章
- 重学c#系列——c# 托管和非托管资源(三)
前言 c# 托管和非托管比较重要,因为这涉及到资源的释放. 现在只要在计算机上运行的,无论玩出什么花来,整个什么概念,逃不过输入数据修改数据输出数据(计算机本质),这里面有个数据的输入,那么我们的内存 ...
- 重学c#系列——字典(十一)
前言 重学c#系列继续更新,简单看一下字典的源码. 看源码主要是解释一下江湖中的两个传言: 字典foreach 顺序是字典添加的顺序 字典删除元素后,字典顺序将会改变 正文 那么就从实例化开始看起,这 ...
- 有关 Azure IaaS VM 磁盘以及托管和非托管高级磁盘的常见问题解答
本文将对有关 Azure 托管磁盘和 Azure 高级存储的一些常见问题进行解答. 托管磁盘 什么是 Azure 托管磁盘? 托管磁盘是一种通过处理存储帐户管理来简化 Azure IaaS VM 的磁 ...
- [.net 面向对象程序设计进阶] (8) 托管与非托管
本节导读:虽然在.NET编程过程中,绝大多数内存垃圾回收由CLR(公共语言运行时)自动回收,但也有很多需要我们编码回收.掌握托管与非托管的基本知识,可以有效避免某些情况下导致的程序异常. 1.什么是托 ...
- NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- C# 托管和非托管混合编程
在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难. 最直接的实现托管与非托管编程的方法就是 ...
- C# using 三种使用方式 C#中托管与非托管 C#托管资源和非托管资源区别
1.using指令.using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到. ...
- 利用C#Marshal类实现托管和非托管的相互转换
Marshal 类 命名空间:System.Runtime.InteropServices 提供了一个方法集,这些方法用于分配非托管内存.复制非托管内存块.将托管类型转换为非托管类型,此外还提供了在与 ...
- [转]C# 之DLL调用(托管与非托管)
每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基于win 32平台开发的DLL,activeX ...
随机推荐
- 【转】HBase的MapReduce调用
参考: https://blog.csdn.net/u012848709/article/details/83744699 自己照着搭建了下,顺便把坑也踩了下,项目见云盘: 链接:https://pa ...
- ubuntu添加新的分辨率选项(干货)
ubuntu默认可选的分辨率不能够满足我的需求,在这里记录增加1440*900分辨率的过程 1. 终端输入: cvt 1440 900 2. 修改配置文件: vim /etc/profile xran ...
- Hexo快速构建个人小站-Fulid主题下添加Valine评论系统(三)
Hexo目录: Hexo快速构建个人小站-Hexo初始化和将项目托管在Github(一) Hexo快速构建个人小站-自定义域名和自定义主题(二) 背景交代: 前面两章完成了Hexo的初始化和部分自定义 ...
- Java常见23中设计模式之【代理模式】
一.静态代理模式 静态代理,使用继承的方式实现自己新增的服务 这种模式可以实现帮助被代理者完成一些前期的准备工作和后期的善后工作,但是核心的业务逻辑仍然是由被代理者完成. 在某些情况下,一个客户不想或 ...
- Spring Cloud Alibaba基础教程:Nacos 生产级版本 0.8.0
昨晚Nacos社区发布了第一个生产级版本:0.8.0.由于该版本除了Bug修复之外,还提供了几个生产管理非常重要的特性,所以觉得还是有必要写一篇讲讲这次升级,在后续的文章中也都将以0.8.0版本为基础 ...
- SpringBoot集成Spring Security
1.Spring Security介绍 Spring security,是一个强大的和高度可定制的身份验证和访问控制框架.它是确保基于Spring的应用程序的标准 --来自官方参考手册 Spring ...
- css3动画的性能优化_针对移动端卡顿问题
这篇文章主要讲的是怎样制作流畅动画,特别是针对移动端.在这里我首先介绍制作动画的几种方法的优缺点:接着会着重介绍用css3制作动画的注意事项. 资源网站大全 https://55wd.com 设计导航 ...
- JSOI2016 病毒感染(动态规划)
题目传送门:洛谷P5774 思路来源:郭大佬(我就是凑不要脸的白嫖党 : P) 题目分析: 我们一点点来分析这道题: 起点固定为1号,所有村庄是按线性排列的,而不是图,所以我们应该用线性DP(废话 ) ...
- 在react中使用到的好用的插件
1)antd UI组件 蚂蚁金服出品的 挺好用的 还有个移动端的antd-moblie 2) moment 日期处理类库 3)prop-types 第三方库 对组件props变量进行类型检测 4)qs ...
- Activity启动流程分析
我们来看一下 startActivity 过程的具体流程.在手机桌面应用中点击某一个 icon 之后,实际上最终就是通过 startActivity 去打开某一个 Activity 页面.我们知道 A ...