首页 > 系统相关 >golang内存管理

golang内存管理

时间:2024-03-13 22:48:12浏览次数:14  
标签:mspan 管理 mcentral sweepgen golang 内存 span page

 

解释定义:

mheap:用于管理整个堆内存,mheap 管理多个arena,arena管理多个span,一个span由多个page组成,一个arena有8192个page,page由内存块组成

mspan:一个span对应一个mspan

mcentral:mheap里有一个全局的mspan管理中心包含mcentral数组,0-135 mcentral,一个mcentral(管理对应类型的span)

 

spanclass高7为是大小编号,最后一位0代表是指针,1代表不是指针

另外分已用尽full和未用尽partial,里面又分已清扫的spanSet和未清扫的spanSet,spanSet是并发安全的。如果所有人都来mcentral要内存,那加锁太频繁了,那么自然而然每个P都有本地的小对象缓存

mcache:每个P内部的小对象缓存。alloc 0-135 *mspan,先在本地找,不够了去mcentral拿一个到本地,用完的放到mcentral的fullset中,tiny 16B,tinyoffset记录这段内存已经用到哪里了,剩下空间还够就继续分配,不够就拿16B大小的内存块过来用,本地缓存的用完了就从mcentral中拿一个新的mspan过来

heapArena:arena 对应一个heapArena 管理者

    type heapArena struct {
        bitmap [heapArenaBitmapBytes]byte 

        spans [pagesPerArena]*mspan  pagesPerArena = 8192 用于定位一个page对应的mspan在哪
        pageInUse [pagesPerArena / 8]uint8  
        pageMarks [pagesPerArena / 8]uint8   
        pageSpecials [pagesPerArena / 8]uint8
        checkmarks *checkmarksMap
        zeroedBase uintptr 标记此 arena 中尚未使用的第一个page的首地址
    }

 

bitmap最后的byte代表一字节分高4位代表终止扫描,低4位代表标量指针。



假设分配一个slice,包含指针,长度,容量。pageInUse 只标记处于使用状态的span的第一个page,例如arena的span 0-1 2-4都使用了,那么第0号元素的pageInUse 第0位标记为1 第2位标记为1

 pageMarks 同pageInUse,只标记哪些span中存在被标记的对象,在gc的时候通过这个位图来释放不含标记对象的span

spans 用于定位一个page对应的mspan在哪

 

type mspan struct {
	next *mspan     // next span in list, or nil if none
	prev *mspan     // previous span in list, or nil if none
	list *mSpanList // For debugging. TODO: Remove.

	startAddr uintptr // address of first byte of span aka s.base()
	npages    uintptr // number of pages in span

	manualFreeList gclinkptr // list of free objects in mSpanManual spans

	// freeindex is the slot index between 0 and nelems at which to begin scanning
	// for the next free object in this span.
	// Each allocation scans allocBits starting at freeindex until it encounters a 0
	// indicating a free object. freeindex is then adjusted so that subsequent scans begin
	// just past the newly discovered free object.
	//
	// If freeindex == nelem, this span has no free objects.
	//
	// allocBits is a bitmap of objects in this span.
	// If n >= freeindex and allocBits[n/8] & (1<<(n%8)) is 0
	// then object n is free;
	// otherwise, object n is allocated. Bits starting at nelem are
	// undefined and should never be referenced.
	//
	// Object n starts at address n*elemsize + (start << pageShift).
	freeindex uintptr
	// TODO: Look up nelems from sizeclass and remove this field if it
	// helps performance.
	nelems uintptr // number of object in the span.

	// Cache of the allocBits at freeindex. allocCache is shifted
	// such that the lowest bit corresponds to the bit freeindex.
	// allocCache holds the complement of allocBits, thus allowing
	// ctz (count trailing zero) to use it directly.
	// allocCache may contain bits beyond s.nelems; the caller must ignore
	// these.
	allocCache uint64

	// allocBits and gcmarkBits hold pointers to a span's mark and
	// allocation bits. The pointers are 8 byte aligned.
	// There are three arenas where this data is held.
	// free: Dirty arenas that are no longer accessed
	//       and can be reused.
	// next: Holds information to be used in the next GC cycle.
	// current: Information being used during this GC cycle.
	// previous: Information being used during the last GC cycle.
	// A new GC cycle starts with the call to finishsweep_m.
	// finishsweep_m moves the previous arena to the free arena,
	// the current arena to the previous arena, and
	// the next arena to the current arena.
	// The next arena is populated as the spans request
	// memory to hold gcmarkBits for the next GC cycle as well
	// as allocBits for newly allocated spans.
	//
	// The pointer arithmetic is done "by hand" instead of using
	// arrays to avoid bounds checks along critical performance
	// paths.
	// The sweep will free the old allocBits and set allocBits to the
	// gcmarkBits. The gcmarkBits are replaced with a fresh zeroed
	// out memory.
	allocBits  *gcBits
	gcmarkBits *gcBits

	// sweep generation:
	// if sweepgen == h->sweepgen - 2, the span needs sweeping
	// if sweepgen == h->sweepgen - 1, the span is currently being swept
	// if sweepgen == h->sweepgen, the span is swept and ready to use
	// if sweepgen == h->sweepgen + 1, the span was cached before sweep began and is still cached, and needs sweeping
	// if sweepgen == h->sweepgen + 3, the span was swept and then cached and is still cached
	// h->sweepgen is incremented by 2 after every GC

	sweepgen              uint32
	divMul                uint32        // for divide by elemsize
	allocCount            uint16        // number of allocated objects
	spanclass             spanClass     // size class and noscan (uint8)
	state                 mSpanStateBox // mSpanInUse etc; accessed atomically (get/set methods)
	needzero              uint8         // needs to be zeroed before allocation
	allocCountBeforeCache uint16        // a copy of allocCount that is stored just before this span is cached
	elemsize              uintptr       // computed from sizeclass or from npages
	limit                 uintptr       // end of data in span
	speciallock           mutex         // guards specials list
	specials              *special      // linked list of special records sorted by offset.

	// freeIndexForScan is like freeindex, except that freeindex is
	// used by the allocator whereas freeIndexForScan is used by the
	// GC scanner. They are two fields so that the GC sees the object
	// is allocated only when the object and the heap bits are
	// initialized (see also the assignment of freeIndexForScan in
	// mallocgc, and issue 54596).
	freeIndexForScan uintptr
}

 

spanclass 跟mcentral一样记录着划分好的内存块规格

nelem 记录当前span共划分成了多少个内存块

freeIndex 记录着下个空闲内存块的索引

allocBits *gcBits 用于标记哪些内存块已经被分配了

gcmarkBits *gcBits 当前span的标记位图,一个二进制位对应span的一个内存块,gc清扫的时候释放allocBits,然后把gcmarkBits用作allocBits,未被gc标记的内存块就能回收利用了

 

申请内存的步骤:

1.辅助gc
至少扫描64KB,多干的部分会存在银行。全局gccontroller有足够多的信用,窃取了也不用进行辅助gc
2.空间分配
<16B noscan tiny
>=16B <=32KB noscan scannable
>32KB 大块内存分配器 需要多少字节就分配一个对应大小的新的span
3.位图标记

*heapArena放到一个数组里,并用arena编号作为索引定位heapArena windows/linux架构arena大小不同,所以有二维数组的说法,计算出arenaidx
amd64 windows第一维64,占6bit,第二维数组长度为1M=2^20,arenaidx中低20位用作第二维的索引
amd64 linux第一维一个元素,第二维4M=2^22,arenaidx中低22位用作第二维的索引
每个arena中有pagesPerArena个page,每个page大小是pageSize,一个内存块的page编号=(p/pageSize)%pagesPerArena,最终能在heapArena数组中找到mspan地址了
4.收尾工作

当前处于gc标记阶段,需要对新分配的对象进行gc标记,这次内存分配达到了触发gc的条件,还会触发新一轮的gc

标签:mspan,管理,mcentral,sweepgen,golang,内存,span,page
From: https://www.cnblogs.com/twh233/p/18071711

相关文章

  • 【华为OD】C卷真题 100分:堆内存申请 C语言代码实现[思路+代码]
     C++、python、java代码:【华为OD】C卷真题100分:堆内存申请C/C++代码实现[思路+代码]-CSDN博客【华为OD】C卷真题100分:堆内存申请Python代码实现[思路+代码]-CSDN博客【华为OD】C卷真题100分:堆内存申请Java代码实现[思路+代码]_有一个总空间为100字节的堆,现要从中新......
  • 大华智慧园区综合管理平台 getNewStaypointDetailQuery SQL注入
    简介大华智慧园区解决方案通过AI技术的加载实现园区安防与园区办公应用的智慧化升级,提升企业安全等级和办公效率;将物联网应用神经延伸至企业各种业务场景,实现人、车、物数据信息线上融合与计算,为园区智慧化管理提供数据源;构建园区大数据平台,向下汇聚各类业务子系统数据,向上为......
  • 1.1程序的内存模型
    1.1内存的分区模型C++程序在执行时,将内存大方向划分为4个区域代码区:存放函数体的二进制代码,由操作系统进行管理的。全局区:存放全局变量和静态变量以及常量。栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。堆区:由程序员分配和释放,若程序员不释放,程序结束时由操......
  • 【开源】SpringBoot框架开发人事管理系统
    目录一、摘要1.1项目介绍1.2项目录屏二、功能模块2.1管理员功能模块2.2普通员工功能模块2.3答辩文案三、系统展示四、核心代码4.1查询职称4.2新增留言回复4.3工资申请4.4工资审核4.5员工请假五、免责说明一、摘要1.1项目介绍基于JAVA+Vue+SpringBo......
  • 【开源】SpringBoot框架开发班级考勤管理系统
    目录一、摘要1.1项目介绍1.2项目录屏二、功能模块2.1系统基础支持模块2.2班级学生教师支持模块2.3考勤签到管理2.4学生请假管理三、系统设计3.1功能设计3.1.1系统基础支持模块3.1.2班级学生教师档案模块3.1.3考勤签到管理模块3.1.4学生请假管理模块3.2......
  • 【开源】SpringBoot框架开发假日旅社管理系统
    目录一、摘要1.1项目介绍1.2项目录屏二、功能模块2.1系统介绍2.2QA问答三、系统展示四、核心代码4.1查询民宿4.2新增民宿评论4.3查询民宿新闻4.4新建民宿预订单4.5查询我的民宿预订单五、免责说明一、摘要1.1项目介绍基于JAVA+Vue+SpringBoot+MySQ......
  • Node+Vue毕设高校教师项目申报管理平台(程序+mysql+Express)
    本系统(程序+源码)带文档lw万字以上 文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:在高等教育领域,教师参与科研项目是推动学科发展和创新的重要途径。随着科研竞争的加剧,高校教师需要积极申报各类科研项目以获取资金支持。然而,项目申报过程......
  • Node+Vue毕设高校实践活动管理平台(程序+mysql+Express)
    本系统(程序+源码)带文档lw万字以上 文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:在全面提升学生实践能力和创新精神的当代教育背景下,高校实践活动成为了教学体系中不可或缺的一部分。这些活动包括社会实践、科研实践、志愿服务、技能培训......
  • DevOps软件开发管理模式、CICD概念及其Jenkins使用
    一、什么是DevOpsDevOps是Develop与Operations的缩写,是开发和运营维护的总称。它是企业内开发、技术运营和质量保障这三方面工作的融合,用于促进开发、技术运营和质保部门之间的沟通、协作与整合。为巩固软件设计与开发结果,将开发、运维与测试结合一起,形成了DevOps软件开发管......
  • Node+Vue毕设风投项目管理(程序+mysql+Express)
    本系统(程序+源码)带文档lw万字以上 文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:在当今快速发展的科技与经济时代,风险投资(VentureCapital,简称VC)扮演着至关重要的角色。它为初创企业和创新项目提供了必要的资金支持,帮助它们在市场中站稳脚......