首页 > 系统相关 >golang 内存分配

golang 内存分配

时间:2023-11-22 21:35:28浏览次数:46  
标签:对象 分配 golang 内存 page mheap

golang的内存分配思想从 tcmalloc 而来,思路是把对象分配成小对象减少锁的力度或无锁增加效率

定义

golang 内部的页(Page)大小为 8B

空间大小

golang 内部把要申请或使用的空间大小分为了三大类:微对象 (<16B),小对象(16B~32KB),大对象(>32KB), 其中小对象又分为 67 种,定义在src/runtime/sizeclasses.go中,在实际分配时候会用向上取整的方式寻找最合适的大小,第 0 种代表是大对象

mspan

mspan(源码src/runtime/mheap.go)是包含了 n 个页的集合,内部有两个字段startAddrnpages,分别代表 page 的开始地址,和一共几个 page. 还有spanclass字段表示该 mspan 是哪种对象的集合(上述定义的 67 种的一种)

mcache

mcache (源码src/runtime/mcache.go)是绑定在GMP模型中 P 上的缓存对象,里面存放了136 种对象(672 下标是 0 是大对象,这里便于计算 加上了 0,用了 682 个),分别代表 67 个对象的分配,其中*2 代表了对象内是否包含指针,用于优化 gc

mcentral

mecntral(源码src/runtime/mcentral.go)也是代表了一种对象,但是保存了从 mheap 申请的内存块,包括带指针和不带指针的, 67 种类型.每一种类型对应一个 mcentral,也就是一种类型一个锁

mheap

mheap(源码src/runtime/mheap.go)保存了全局的对象,从内存分配的对象先由 mheap 托管,同时,大文件(>32KB)文件也是直接从 mheap 申请,拥有全局锁

预申请

golang 在 64 位的操作系统上会预先申请一整块内存用于分配

arena 就是所说的内存分配区域,所有的页都保存在 arena 区域,大小为 512GB,一个页8B,所以一次申请了512GB/8B = 6410241024*1024 个page

bitmap 每个 page 在 bitmap 中用两个位标记对应地址中是否存在对象,另外是标记此对象是否被gc标记过,所以一共占用 512GB/4*8B = 16GB 大小的空间

spans 里面存放了 mspan 的集合,每个 mspan 里面存放 n 个page ,span 主要是一种大小的数据,这个主要是根据 golang 内定的 67 种普通大小的 span,每种类型的 span 内部 page 大小不一定,比如第一种大小是 8B,那么里面就存放了 1 个 page,这个 span 就可以分配 1024 个8B 大小的空间,这里也没啥公式,在源码 src/runtime/sizeclasses.go,可以查到所有的 span 类型,spans 一共占用了 512MB 的空间,但有一点,span 内部的 page 一定是连续的

分配

在 goroutine 在运行时进行内存申请,分配器会先判断是什么类型的对象

case 微对象:
微对象会用 tinymalloc 微对象分配器,同时会对对象进行内存对齐,比如 3B 的对象分配 4B,7B 的对象分配 8B,这块在源码有,就不详说了,如果空间不够就会一层一层向上找,同小对象

case 大对象:
大对象直接从 mheap 上申请,同时由于可能并发,所以一定是加锁获取的

case 小对象:
小对象在 golang 中最常见,所以,分配规则也是最复杂的 首先去 mcache 中申请,由于 mcache 是绑定在 P (GMP) 上的,所以不会发生竞争,这块不用加锁,分配器根据申请的对象大小,向上取整,找到对应的 67 种类型的一种,然后返回. 当 mcache 中的该类型内存不够分配时,分配器去先去mcentral对应的类型下的 mspan 申请,然后放到P 的mcache 中,这个过程由于可能多个 goroutine 竞争,所以会有锁 当该类型的 mcentral 中的空间也不够时,分配器会去 mheap中申请 mheap 最后给 goroutine 分配 最后如果 mheap 中的内存也不够了,那么这时候,就需要重新去操作系统申请了(mmap),操作系统也么有就会 oom

参考

10分钟掌握golang内存管理机制
详解Go语言的内存模型及堆的分配管理
图解Go语言内存分配
go需要自己管理内存吗,为什么面试都爱问内存管理呢? - 小徐先生的回答 - 知乎
Golang源码探索(三) GC的实现原理

标签:对象,分配,golang,内存,page,mheap
From: https://www.cnblogs.com/elve960520/p/17850344.html

相关文章

  • golang 原子操作
    在golang中,有原子包,能够实现原子操作,在我分析和猜想下,感觉解开了谜团具体用法不说了,网上一大堆什么cas,add,load,store等,主要是底层实现arm架构在amd架构下,通过汇编指令加锁来实现代码在src/runtime/internal/atomic/atomic_amd64.s//uint64Xadd64(uint64volatile*va......
  • golang select
    golangselect是多channel并行的利器不要拿switch和select比,根本不是一个东西好嘛,差不少,只是名字稍微有点像前置操作golang对select做了一些优化select结构体为空当select里面为空的时候会直接panic只有一个case当只有一个case时候(包括只有一个case时候),......
  • 三种初始化以及内存分析
    packagearray;publicclassArrayDemo02{publicstaticvoidmain(String[]args){//静态初始化:声明+创建+赋值一起做好了int[]a={1,2,3,4};System.out.println(a[0]);//动态初始化:包含默认初始化没有被赋值的如果想输......
  • Golang Gin 模板基本使用
    一,模板定义,模板变量,条件判断,模板函数,模板命名1{{define"default/index.html"}}2<!DOCTYPEhtml>3<htmllang="en">45<head>6<metacharset="UTF-8">7<metaname="viewport"conte......
  • 数据库服务器开启内存大页优化及机制
    一、背景在一次Oracle数据库健康检查报告中,显示PageTables所占用内存过大,建议配置大页PageTables(页表):用于将内存的虚拟地址翻译成物理地址,随着内存地址分配得越来越多,这个需要从Linux分页了解起二、Linux分页在计算机操作系统中,内存分页是一种内存管理方案,也是现代操作系统......
  • Python在使用pandas时内存使用过大导致服务器宕机,有哪些优化方法?
    当使用pandas处理大规模数据时,内存使用量可能会迅速增加,导致服务器宕机。为了解决这个问题,可以采用以下几个优化方法:数据类型优化:使用更小的数据类型,例如将int64转换为int32或int16,节省内存空间。对于字符串类型,尽量使用'category'类型,它会使用更少的内存。分块处理:使......
  • Golang Gin 初识
    1.Gin框架搭建,初识1//main.go2packagemain34/***5Gin入门:6文档:https://gin-gonic.com/zh-cn/docs/quickstart/7热加载:8文档:https://github.com/cosmtrek/air/blob/master/README-zh_cn.md9安装:g......
  • 【Java基础】内存分配
    1.栈方法运行时所进入的内存2.堆需要new的引用数据类型会在堆内存中开辟空间并产生地址堆内存中的数据在生命周期结束后会由垃圾回收器不定时回收(C语言需要手动写代码清理释放内存空间)3.方法区字节码文件加载时进入的内存4.本地方法栈(辅助虚拟机)---了解5.寄存......
  • 【golang】【注释模版】
    @目录写在前面注释要求package结构体方法代码逻辑注释参考资料基础/标准库/第三方库golang导航编程规范算法|面试项目写在前面相关博文个人博客首页免责声明:仅供学习交流使用!开源框架可能存在的风险和相关后果将完全由用户自行承担,本人不承担任何法律责任。注释要求统......
  • 解锁数据库运维秘籍:掌握AntDB-T动态共享内存,提升进程间通信效率
    动态共享内存是AntDB数据库通信的重要手段,本文主要阐述AntDB-T数据库动态共享内存的实现原理、实现方式与使用方法。AntDB-T数据库是一款企业级通用分布式关系型数据库,其数据库内核是基于进程模型实现的,因此进程间通信(IPC)是实现分布式架构间进行任务协作和数据共享的关键。实现进......