iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >ASP.Net Core中的内存和GC机制
  • 178
分享到

ASP.Net Core中的内存和GC机制

2024-04-02 19:04:59 178人浏览 薄情痞子
摘要

托管代码 在 .net 中, CLR(Common Language Runtime) 负责提取托管代码并编译成机器语言,然后执行它。在此过程中,CLR 提供自动内存管理、

托管代码

.net 中, CLR(Common Language Runtime) 负责提取托管代码并编译成机器语言,然后执行它。在此过程中,CLR 提供自动内存管理、安全边界、类型安全等服务,保证了代码安全。

托管代码指在其执行过程中由 CLR(Common Language Runtime) 管理的代码,托管代码是可在 .NET 上运行得一种高级语言(C#、F#等),编写的托管代码被编译后会被生成 中间语言(IL)。

CLR 有 .net core/.NET5+、Mono、.NET Framework 等实现,托管代码生成的文件(IL代码)不能被操作系统直接运行,需要 CLR 的实现(如 .NET5) 托管运行,托管过程中对其再次编译生成二进制代码(JIT编译)。

中间语言(IL)有时也称为公共中间语言 (CIL) 或 Microsoft 中间语言 (MSIL)。

自动内存管理

自动内存管理是 CLR 的功能之一,它可以为应用程序管理内存的分配和释放,托管代码被执行时,由 CLR 进行内存管理,保证了内存安全。

垃圾回收

GC

GC(garbage collector)中文译为垃圾回收器,.NET 中的 GC 指的是 CLR 中的自动内存管理器,GC 负责管理 .NET 程序的内存分配和释放。

GC 的优点如下:

  • 自动管理内存,不必手动分配和释放;

  • 高效管理托管堆上的对象;

  • 智能回收对象,清除内存;

  • 内存安全:避免野指针、悬空指针等情况造成严重错误;

内存

物理内存

物理内存是物理内存条上的内存空间,是物理机器真实的容量大小。

虚拟内存

虚拟内存(Virtual Memory)是计算机操作系统进行内存管理的一种技术,它可以将多个硬件、非连续地址的碎片空间组合起来,形成进程上可识别的连续内存空间。

虚拟内存由操作系统进行支持,如 windows 上的虚拟内存,linux 上的交互空间,虚拟内存需要操作系统映射到真实的内存地址空间才能使用。虚拟内存调度方式有分页式、段式、段页式3种,读者感兴趣可自行查阅资料。

现代操作系统都采用了虚拟内存管理技术,通过对物理存储设备的抽象,操作系统调度外存当作内存使用,提供了比物理内存更大的内存范围。

这些存储设备组成的内存称为虚拟地址空间,而用户(开发者)接触到的地址是虚地址,并不是真实的物理地址。虚拟空间大大拓展了内存,使得系统可以同时运行多道程序而不“吃力”。

虚拟地址空间分为两部分:用户空间、内核空间,每个程序运行时的会消耗两种空间。在 Linux 中比例是 3:1,在 Windows 中是 2:2。

.NET 内存组成

.NET 中,内存分为非托管内存、托管内存。

.Net Core/.NET5+ 有一个称为 dotnet 的驱动程序,此驱动程序用于执行命令或运行 .NET 程序。当我们使用 dotnet 命令运行一个 .dll 文件时,操作系统会启动 dotnet 驱动程序,此时会分配操作系统内存资源、dotnet 驱动程序内存资源,这一部分即非托管资源,其中 dotnet 部分的内存包含了 CLR 等部件的内存。即使你并没有使用到 C/C++ 等非托管代码或者使用非托管资源,也会使用到非托管内存。

接下来 CLR 将初始化新进程,CLR 将为其分配托管内存(托管堆),这段托管内存是一个连续的地址空间区域。.NET 安全代码只能使用托管内存,不能直接使用物理内存,垃圾收集器会为安全代码在托管堆上分配和释放虚拟内存。

显然, dotnet 的工作原理十分复杂,笔者没有能力讲清楚,感兴趣的读者可以自行查阅资料。

CLR 中的内存

微软 .NET CLR 文档中写道:By default, on 32-bit computers, each process has a 2-GB user-mode virtual address space.

即在 32 位系统中,.NET 进程会使用 2GB 的用户模式虚拟内存,其虚拟地址空间的表示范围是 0x00000000 到 0x7fff;而 64 位系统中,地址范围是 0x000'00000000 到0x7FFF'FFFFFFFF,约等于 16TB。

从以上信息,我们知道 .NET 程序会消耗比较多的虚拟内存,如果在 64 位操作系统上运行 .NET 程序,其用户模式虚拟地址空间可能远远大于 2GB。

编写一个 "c1" 程序,其代码如下:

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Console.Read();
        }

在 Linux 中使用 dotnet xx.dll 命令运行程序,然后查看其占用的资源:

 VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  3.1g   0.0g   0.0g S   0.3   0.3   0:00.83 dotnet

使用 dotnet-counters 查看 dotnet 进程:

    GC Heap Size (MB)                                              0
    Gen 0 GC Count (Count / 1 sec)                                 0
    Gen 0 Size (B)                                                 0
    Gen 1 GC Count (Count / 1 sec)                                 0
    Gen 1 Size (B)                                                 0
    Gen 2 GC Count (Count / 1 sec)                                 0
    Gen 2 Size (B)                                                 0
    LOH Size (B)                                                   0

注:使用 dotnet run 运行 .NET 项目,会出现 dotnet、c1 两个进程,可以看到会产生 dotnet 和 c1 两个进程,dotnet 是驱动程序,dotnet 启动后,CLR 会将. dll 程序集编译,并初始化启动一个进程。

CLR 中的虚拟地址空间需要位于一个地址块中,因为在请求虚拟内存分配时,虚拟内存管理器必须找到满足需求的单个可用块,例如就算存在大于 2GB 的虚拟地址空间,但如果不是连续的,则会分配失败。如果没有足够的可供保留的虚拟地址空间或可供提交的物理空间,则可能会用尽内存。

CLR 虚拟内存状态

CLR 中的虚拟内存可以有三种状态:

StateDescription
Free 可用The block of memory has no references to it and is available for allocation. 内存块没有对它的引用,可以进行分配
Reserved保留The block of memory is available for your use and cannot be used for any other allocation request. 该内存块可供您使用,不能用于任何其他分配请求 However, you cannot store data to this memory block until it is committed. 但是,在提交数据之前,不能将数据存储到此内存块中
Committed已提交The block of memory is assigned to physical storage. 内存块已指派给物理存储

内存分配

CLR 在初始化新进程时,会为进程保留一个连续的地址空间区域,这个地址空间被称为托管堆。托管堆中维护着一个指针,最初此指针指向托管堆的基址,这个指针是向后移动的。当需要分配内存时,CLR 便会分配位于此指针后的内存区域,同时指针指向此对象地址空间之后的位置。

由于 CLR 通过向指针添加值来为对象分配内存,所以它的分配速度几乎跟从堆栈中分配内存速度一样快;而且连续分配的新对象连续存储在托管堆中,程序可以快速地访问这些对象。

当 GC 回收内存时,一些对象释放后内存会被回收,这样托管堆地内存处于碎片化,之后整个内存段会被压缩,重新组成连连续的内存段,指针会被重置到对象的末尾。

当然,大对象堆(LOH)回收并不会压缩内存段,这一点我们后面再讨论。

内存释放

垃圾回收的条件

根据微软官方文档,整理的垃圾回收条件如下:

  • 系统物理内存不足;
  • 托管堆分配的内存已超出可接受阈值;(当然,这个阈值会被动态调整)
  • 手动调用 GC 类的 api(例如 GC.Collect);

托管堆

本机堆(Native Heap)

前面提到过,.NET 的内存有非托管内存和托管内存。CLR 运行的进程,存在本机堆和托管堆两种内存堆,本机内存堆通过 Windows API 的 VirtualAlloc 函数分配,提供给 操作系统和 CLR 使用,用于非托管代码所需的内存。

托管堆(Managed Heap)

关于托管堆,前面已经写了,这里不再赘述。

托管堆代数

托管堆中的内存被分为三代,分别使用0、1、2 标识,GC 分配的内存首先在 0 代托管堆中,当进行垃圾回收时,如果对象没有被释放,则将其升级并存储到 1 代托管堆中。1 代托管堆进行内存回收时,不被释放的对象也会被升级到 2 代内存中,然后 1 代内存堆进行空间压缩。

托管堆的管理是 GC 负责的,而 GC 进行内存分配和释放,使用了 GC 算法

GC 算法基于以下理论:

  • ① 压缩托管堆的一部分内存要比压缩整个托管堆速度快;
  • ② 较新的对象生命周期较短,较旧的对象生命周期较长;
  • ③ 较新的对象趋向于相互关联,并且大约在同一时间被应用程序访问;

我们必须深刻理解这些理论,才能深入理解托管堆的设计。

关于 0 到 2 代堆,其基本说明如下:

  • 0 代:0 代中的对象拥有短暂的生命周期,垃圾回收最常发生在此代中;
  • 1 代:作为生命周期较短和生命周期较长对象的缓冲区。
  • 2 代:存储生命周期长的对象;0、1 代没被回收而升级的对象会升级到 2 代中,静态数据等则会一开始就分配到 2代。

在 .NET 5 之前,.NET 有 SOH(小对象堆)、LOH(大对象堆);在 .NET 5 中,出现了 POH ;

小对象堆的内存段有 0、1、2 代堆;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: ASP.Net Core中的内存和GC机制

本文链接: https://www.lsjlt.com/news/144402.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • ASP.Net Core中的内存和GC机制
    托管代码 在 .NET 中, CLR(Common Language Runtime) 负责提取托管代码并编译成机器语言,然后执行它。在此过程中,CLR 提供自动内存管理、...
    99+
    2024-04-02
  • ASP.NET Core中的通用主机HostBuilder
    目录1.前言2.介绍3.设置主机4.选项4.1关闭超时值5.默认服务6.主机配置6.1ConfigureHostConfiguration6.2ConfigureAppConfigu...
    99+
    2024-04-02
  • ASP.NET Core中的通用主机HostBuilder
    ASP.NET Core中的通用主机HostBuilder是一个用于构建和配置应用程序主机的实用程序类。它提供了一种简单的方式来创建...
    99+
    2023-08-14
    ASP.NET
  • 在ASP.NET Core中应用HttpClient获取数据和内容
    目录概述关于HttpClient在ASP.NET Core中使用HttpClient发送GET请求支持不同的响应格式HttpClient中的优先级使用HttpRequestMessa...
    99+
    2024-04-02
  • Go语言中的GC机制详解
    标题:Go语言中的GC机制详解 Go语言作为一种现代化且高效的编程语言,其垃圾回收(Garbage Collection,GC)机制一直是其亮点之一。GC机制的设计使得开发者可以更加专...
    99+
    2024-04-02
  • ASP.NET Core 中间件的使用之全局异常处理机制
    目录1、创建项目2、创建全局异常过滤器3、依赖注入全局异常处理机制4、测试全局异常处理机制前言: 我们经常听到“秒修复秒上线”,觉得很厉害的样子。 其实不然,这只是一个调侃而已,出...
    99+
    2024-04-02
  • Node.js中GC机制的示例分析
    这篇文章主要为大家展示了“Node.js中GC机制的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Node.js中GC机制的示例分析”这篇文章吧。V8 ...
    99+
    2024-04-02
  • 图文详解Node V8引擎的内存和GC
    阶段二 并行多线程GC(代表:Parallel Scavenge, ParNew)在多 CPU 环境中利用多条 GC 线程同时并行运行,从而垃圾回收的时间减少、用户线程停顿的时间也减少,这个算法也会STW,完全暂停其他所有的工作线程阶段三 ...
    99+
    2023-05-14
    Node.js 后端 V8
  • ASP.NET Core中的策略授权和ABP授权
    目录ASP.NET Core 中的策略授权策略定义一个 Controller设定权限定义策略存储用户信息标记访问权限认证:Token 凭据颁发登录凭据自定义授权IAuthorizat...
    99+
    2024-04-02
  • 【python内存机制】引用和赋值
    1 引用和对象 1.1> 创建变量的过程 内存创建对象 --> 创建变量 --> 变量引用到对象 因此:变量只是到内存对象的一个引用 1.2> 对象组成...
    99+
    2023-01-31
    赋值 机制 内存
  • Linux内存机制的介绍
    这篇文章主要介绍“Linux内存机制的介绍”,在日常操作中,相信很多人在Linux内存机制的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux内存机制的介绍”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-13
  • JVM之内存分配和回收机制
    目录一、内存分配策略二、对象存活1.引用计数算法2.可达性分析算法3.再谈引用三、内存回收1.堆内存回收2.方法区回收总结前言 本篇主要介绍JVM内存分配和回收策略,内容主要节选自《...
    99+
    2023-05-18
    JVM内存分配 java内存回收
  • 详解CLR的内存分配和回收机制
    一、CLR CLR:即公共语言运行时(Common Language Runtime),是中间语言(IL)的运行时环境,负责将编译生成的MSIL编译成计算机可以识别的机器码,负责资源...
    99+
    2024-04-02
  • Python的内存管理和垃圾回收机制
    本篇内容介绍了“Python的内存管理和垃圾回收机制”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!对象的内存使用赋值语句是语言最常见的功能了...
    99+
    2023-06-02
  • Python中的内存管理的原理和机制是什么,如何避免内存泄漏?
    Python中的内存管理的原理和机制是什么,如何避免内存泄漏?Python作为一门高级语言,通过自动内存管理提供了方便的编程环境。Python的内存管理主要依靠垃圾回收机制来实现,通过引用计数和循环垃圾回收来管理和释放内存。在Python中...
    99+
    2023-10-22
    内存管理:内存管理 原理:原理 内存泄漏:内存泄漏
  • 图文详解PHP中GC回收机制的利用
    目录前言简单铺垫初识GC小试牛刀总结前言 在前面讲魔术方法时就提到过一个问题,__destruct()无论如何都会被触发,但是前提是必须得完成程序的开始与结束,但是如果程序走了一半,...
    99+
    2024-04-02
  • 怎么在 ASP.NET Core 中使用内置的 Json 格式化日期
    这篇文章主要介绍“怎么在 ASP.NET Core 中使用内置的 Json 格式化日期 ”,在日常操作中,相信很多人在怎么在 ASP.NET Core 中使用内置的 Json 格式化日期 问题上存在疑惑,小...
    99+
    2024-04-02
  • 如何利用ASP.NET Core实现高效的大数据存储和管理?
    ASP.NET Core是一种开源的Web框架,可以帮助开发人员快速创建高性能的Web应用程序。当涉及到大数据的存储和管理时,ASP.NET Core可以提供许多有用的工具和功能,使这个过程更加高效和可靠。下面我们将介绍如何利用ASP.NE...
    99+
    2023-07-10
    大数据 leetcode linux
  • 深入浅析Java中的内存分配机制
    本篇文章给大家分享的是有关深入浅析Java中的内存分配机制,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java 内存分配深入理解Java程序运行在JVM(Java ...
    99+
    2023-05-31
    java 内存分配 ava
  • Python中什么是内存管理机制
    本篇文章给大家分享的是有关Python中什么是内存管理机制,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。python的数据类型有哪些python的数据类型:1. 数字类型,包括...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作