当前位置:首页 > 内存 > 正文

根据对象的类型分配内存空间

  • 内存
  • 2024-06-11 06:06:40
  • 7896

一、Golang1.14中内存分配、清扫和内存回收

Golang的内存分配是由golangruntime完成的,其内存分配系统借鉴了tcmalloc。
主要特点是

本文中的元素指的是一定大小的内存块,这是内存分配的概念,出现在golangruntime的源码中
本文讲的是x8664架构下的内存分配

Golang内存分配有以下主要结构

小对象是指内存大小小于16字节的对象,这些对象是使用小的mcache空间分配。当tiny区域空间不足时,它会寻找[tinySpanClass]指向的mspan的一个空区域。当然,如果mcache中的span空间也耗尽了,这会触发mcentral到mcache的mspan补货过程。

小对象是指大小范围在(16B,32KB)之间的对象。分配这些对象的原则是:
1.首先,根据对象的大小将对象分类到某个SpanClass中,SpanClass中的所有对象都具有相同的大小。
2.从[SpanClass]中找到mspan,检查是否有空闲元素,如果没有,从pan[SpanClass]中找到合适的非空和空mspan,返回给mcache。如果没有找到,则进入()—>()为mcentral分配一个新的mspan指向大小超过32KB的对象,此时直接从mheap中分配,不使用mcache和mcentral,而不是因此,()用于分配SpanClass==0的mspan来表示分配的空间的该部分。

对于软件分配中常用的小对象和小对象的分配,可以通过无锁缓存来提高分配性能。当cache不足时,会拿mcentral锁,然后直接将mspan填充到从mheap分配的mcache中。

在x8664环境下,golang管理的有效软件虚拟地址空间实际上只有48位。mheap中有一个pagespageAlloc成员,用于管理golang堆中的地址空间。向操作系统请求地址空间并自行管理。申请地址空间后,golang会根据实际使用情况将地址空间标记为空闲或已分配,如果地址空间分配为mspan或large,则会标记为已分配,反之亦然。

Golang认为地址空间有以下四种状态:

Golang还定义了以下地址空间。操作功能:

在mheap结构体中,有一个名为heap的成员,它用于使用虚拟地址空间来管理Golang堆。它的类型是pageAlloc

结构体pageAlloc代表golang堆中的所有地址空间。有两个重要的成员:

在golang的gc过程中,未使用的对象会被标记为未使用,但这些对象使用的地址空间不会被返回。操作系统实现和地址空间版本都依赖于golang。它以页面为单位(实际上是以修剪单位)实现。扫描过程的最终结果只是选择了特定的地址空间进行分配,并没有真正释放该地址空间给操作系统。真正的版本是后面的扫描过程。

gcmark完成后,将使用clear()操作来尝试释放句点;当应用于mspan时,也会使用sweep进程来清理它。
mspan扫描进程主要包括以下功能

上一节提到,mspan扫描进程只是将页面标记为可定制,但并没有释放真实的地址空间,也就是扫描过程。
真正的搜索是通过ge()—>sysUnused()释放扫描到的要编辑的段所代表的地址空间(使用sysUnused()将地址空间返回给操作系统)
golang有两种搜索操作: