当前位置: 首页 > news >正文

Golang内存模型与分配机制

简述

在这里插入图片描述
mheap为堆,堆和进程是一对一的;mcentral(小mheadp),mcahe(GMP的P私有),分配内存顺序由后向前。
在解决这个问题,Golang 在堆 mheap 之上,依次细化粒度,建立了mcentral、mcache 的模型,下面对三者作个梳理:

  • mheap:全局的内存起源,访问要加全局锁
  • mcentral:每种对象大小规格(全局共划分为68种)对应的缓存,锁的粒度也仅限于同一种规格以内
  • mcache:每个P(正是GMP中的P)持有一份的内存缓存,访问时无锁
    在这里插入图片描述
    首先理下page和mspan两个概念∶
    (1) page:最小的存储单元.
    Golang 借鉴操作系统分页管理的思想,每个最小的存储单元也称之为页page,但大小为8 KB
    (2) mspan:最小的管理单元.
    mspan 大小为 page 的整数倍,且8B到80 KB被划分为67种不同的规格,分配对象时,会根据大小映射到不同规格的mspan,从中获取空间.
    于是,我们回头小节多规格mspan下产生的特点︰
  • 根据规格大小,产生了等级的制度
  • 消除了外部碎片,但不可避免会有内部碎片
  • 宏观上能提高整体空间利用率
  • 正是因为有了规格等级的概念,才支持mcentral实现细锁化

核心概念梳理

内存单元mspan

在这里插入图片描述
分点阐述mspan的特质:

  • mspan是Golang内存管理的最小单元
  • mspan大小是page的整数倍(Go 中的page 大小为8KB),且内部的页是连续的(至少在虚拟内存的视角中是这样)
  • 每个mspan根据空间大小以及面向分配对象的大小,会被划分为不同的等级
  • 同等级的mspan 会从属同一个mcentral,最终会被组织成链表,因此带有前后指针((prev、next)·- 由于同等级的mspan内聚于同一个mcentral,所以会基于同一把互斥锁管理
  • mspan 会基于bitMap辅助快速找到空闲内存块(块大小为对应等级下的object大小),此时需要使用到Ctz64算法.
    在这里插入图片描述
    在这里插入图片描述

内存单元等级spanClass

mspan根据空间大小和面向分配对象的大小,被划分为67种等级(1-67,实际上还有一种隐藏的0级,用于处理更大的对象,上不封顶)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
除了上面谈及的根据大小确定的mspan等级外,每个object还有一个重要的属性叫做nocan,标识了object是否包含指针,在gc时是否需要展开标记.
在Golang 中,会将span class + nocan两部分信息组装成一个uint8,形成完整的
spanClass 标识.8个 bit中,高7位表示了上表的span等级((总共67+1个等级,8个bit足够用了),最低位表示nocan信息.
在这里插入图片描述

线程缓存mcache

在这里插入图片描述
(1) mcache是每个Р独有的缓存,因此交互无锁
(2) mcache 将每种spanClass 等级的mspan各缓存了一个,总数为2 (nocan维度)*68(大小维度)=136
(3) mcache 中还有一个为对象分配器tiny allocator,用于处理小于16B对象的内存分配
在这里插入图片描述

中心缓存mcentral

在这里插入图片描述
要点∶
(1)每个mcentral对应一种spanClass
(2)每个mcentral 下聚合了该spanClass 下的mspan
(3) mcentral 下的mspan分为两个链表,分别为有空间mspan链表partial和满空间mspan链表full
(4)每个mcentral一把锁
在这里插入图片描述

全局堆缓存mheap

要点

  • 对于Golang上层应用而言,堆是操作系统虚拟内存的抽象·
  • 以页(8KB)为单位,作为最小内存存储单元
  • 负责将连续页组装成mspan
  • 全局内存基于bitMap标识其使用情况,每个bit对应一页,为0则自由,为1则已被mspan组装·
  • 通过heapArena 聚合页,记录了页到mspan的映射信息
  • 建立空闲页基数树索引 radix tree index,辅助快速寻找空闲页
  • 是mcentral 的持有者,持有所有spanClass 下的mcentral,作为自身的缓存
  • 内存不够时,向操作系统申请,申请单位为heapArena (64M)
    在这里插入图片描述

空闲也索引pageAlloc

数据结构背后的含义:

  • mheap 会基于bitMap标识内存中各页的使用情况,bit位为0代表该页是空闲的,为1代表该页已被mspan占用.
    • 每棵基数树聚合了16 GB内存空间中各页使用情况的索引信息,用于帮助 mheap快速找到指定长度的连续空闲页的所在位置
  • mheap持有214 棵基数树,因此索引全面覆盖到 214*16 GB = 256 T的内存空间.

在这里插入图片描述

  • 每个父 pallocSum有8个子pallocSum
  • 根pallocSum总览全局,映射的 bitMap范围为全局的16 GB空间(其max最大值为221,因此总空间大小为221*8KB=16GB) ;
  • 从首层向下是一个依次八等分的过程,每一个pallocSum映射其父节点bitMap范围的八分之一,因此第二层pallocSum的 bitMap 范围为16GB/8 = 2GB,以此类推,第五层节点的范围为16GB /(84) = 4 MB,已经很小
  • 聚合信息时,自底向上.每个父pallocSum聚合8个子pallocSum的start、max、end信息,形成自己的信息,直到根pallocSum,坐拥全局16 GB的start、max、end 信息
  • mheap寻页时,自顶向下.对于遍历到的每个pallocSum,先看起start 是否符合,是则寻页成功;再看max是否符合,是则进入其下层孩子pallocSum中进一步寻访;最后看end和下一个同辈pallocSum 的start聚合后是否满足,是则寻页成功.

每层节点
在这里插入图片描述
基数树中,每个节点称之为PallocSum,是一个uint64类型,体现了索引的聚合信息,包含以下四部分:

  • start:最右侧21个bit,标识了当前节点映射的 bitMap 范围中首端有多少个连续的0 bit(空闲页),称之为start;
  • max:中间21个bit,标识了当前节点映射的 bitMap范围中最多有多少个连续的0 bit(空闲页),称之为max;
  • end:左侧21个 bit,标识了当前节点映射的 bitMap范围中最末端有多少个连续的0 bit(空闲页),称之为end.
  • 最左侧一个bit,弃置不用
    在这里插入图片描述
    基数树节点
    在这里插入图片描述
    在这里插入图片描述

heapArena

  • 每个heapArena包含8192个页,大小为8192* 8KB = 64 MB
  • **heapArena记录了页到msplan的映射.**因为GC时,通过地址偏移找到页很方便,但找到其所属的mspan不容易.因此需要通过这个映射信息进行辅助.
  • heapArena是mheap向操作系统申请内存的单位(64MB)
    在这里插入图片描述

对象分配流程

下面来串联 Golang中分配对象的流程,不论是以下哪种方式,最终都会殊途同归步入mallocgc方法中,并且根据3.1小节中的策略执行分配流程:

  • new(T)
  • &T{}
  • make(xxxx)

分配流程总览

Golang中,依据 object的大小,会将其分为下述三类∶

  • tiny微对象(0-16B)
  • small小对象(16B-32KB)
  • large大对象(32KB—)

不同类型的对象,会有着不同的分配策略,这些内容在mallocgc方法中都有体现.
核心流程类似于读多级缓存的过程,由上而下,每一步只要成功则直接返回.若失败,则由下层方法兜底.

对于微对象的分配流程︰

(1)从P专属mcache 的tiny 分配器取内存(无锁)
(2)根据所属的spanClass,从Р专属mcache 缓存的mspan中取内存(无锁)
(3)根据所属的spanClass 从对应的mcentral中取 mspan填充到mcache,然后从mspan中取内存(spanclass粒度锁)
(4)根据所属的spanClass,从 mheap 的页分配器 pageAlloc取得足够数量空闲页组装成mspan填充到mcache,然后从mspan中取内存(全局锁)
(5) mheap向操作系统申请内存,更新页分配器的索引信息,然后重复(4) .

对于小对象的分配流程是跳过〔1)步,执行上述流程的(2) - (5)步;

对于大对象的分配流程是跳过(1)-(3)步,执行上述流程的(4) - (5)步.

主干方法,mallocgc

微对象分配
在这里插入图片描述
在这里插入图片描述
小对象分配
在这里插入图片描述
大对象分配
在这里插入图片描述

tiny分配

每个Р独有的mache 会有个微对象分配器,基于 offset线性移动的方式对微对象进行分配,每16B成块,对象依据其大小,会向上取整为2的整数次幂进行空间补齐,然后进入分配流程.
在这里插入图片描述
在这里插入图片描述

mcache分配

在这里插入图片描述
在mspan中,基于Ctz64算法,根据 mspan.allocCache 的 bitMap信息快速检索到空闲的object块,进行返回.
在这里插入图片描述

mcentral分配

当mspan无可用的object内存块时,会步入mcache.nextFree方法进行兜底.
在这里插入图片描述
在这里插入图片描述
mcentral.cacheSpan方法中,会加锁(spanClass 级别的sweepLocker),分别从 partial和full中尝试获取有空间的mspan:
在这里插入图片描述

mheap分配

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

操作系统申请

倘若mheap中没有足够多的空闲页了,会发起mmap系统调用,向操作系统申请额外的内存空间.
在这里插入图片描述
在这里插入图片描述

基数树寻页

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

Golang内存模型与分配机制

简述 mheap为堆,堆和进程是一对一的;mcentral(小mheadp),mcahe(GMP的P私有),分配内存顺序由后向前。 在解决这个问题,Golang 在堆 mheap 之上,依次细化粒度&a…...

HarmoneyOS星河版 安装和启动

一、下载和安装DevEco Studio 官网链接:OpenAtom OpenHarmony 1.1 找到对应的操作系统进行下载 创建安装Harmony的文件夹: 1.2 下载后进行安装 1.3 分别安装Node、Ohpm、SDK 分别安装Node、Ohpm和SDK 二、.创建一个新项目并运行 2.1 选择[OpenHarmon…...

奇舞周刊第530期:AIGC和低代码结合应用全栈研发实践总结

周五快乐(图片由midjourney生成) 奇舞推荐 ■ ■ ■ AIGC 和低代码结合应用全栈研发实践总结 得物通过低代码和大模型技术简化电商供应链系统开发。尽管低代码工具存在一些局限,但结合大模型生成脚本和理解配置,提高了效率。未来将…...

linux上运行js脚本

貌似学运维,啥都要懂一点儿?????? 我们将使用 Node.js 和 ES6 模块语法。 首先,确保你已经安装了 Node.js。 创建项目文件结构 假设我们的项目结构如下: my_project/…...

PCA 在图像分析上的应用

同一物体旋转角度求取 直接上代码: import cv2, os import numpy as np import timedef perform_pca(image, num_components):# 将图像转换为浮点型img_float np.float32(image)img_flatten img_float.reshape(-1, 2)# 计算均值和协方差矩阵mean, eigenvectors …...

springboot项目mapper无法自动装配,未找到 ‘userMapper‘ 类型的Bean解决办法.

一开始我看到了这个回答:springboot项目mapper无法自动装配,未找到 ‘userMapper‘ 类型的 Bean解决办法(含报错原因)_无法自动装配。找不到 usermapper 类型的 bean。-CSDN博客 mapper无法自动装配,未找到 ‘userMap…...

TC3xx A\B SWAP机制的小细节(2)

目录 1.引入 2.TC3xx Swap机制小细节 3.小结 1.引入 上文TC3xx A\B SWAP机制的小细节(1)-CSDN博客主要把OTA的概念,以及MCU的硬件A\B Swap机制做了简单介绍,下面我们来聊聊TC3xx的SWAP机制 2.TC3xx Swap机制小细节 英飞凌TC3xx提供了硬件SOTA机制&…...

双绞线(网线)的制作与测试

实验目的 1、熟悉常用双绞线(网线)及其制作工具的使用; 2、掌握非屏蔽双绞线的直通线、交叉线的制作及连接方法; 3、掌握双绞线连通性的测试。 设备要求:RJ45压线钳,RJ45水晶头,UTP线缆&…...

高效处理海量慢SQL日志文件:Java与JSQLParser去重方案详解

在大数据处理环境下,慢SQL日志优化是一个必要的步骤,尤其当日志文件达到数GB时,直接操作日志文件会带来诸多不便。本文将介绍如何通过Java和JSQLParser库来解析和去重慢SQL日志,以提高性能和可维护性。 背景 公司生产环境中&…...

企业内部、与合作伙伴/客户文档协作如何高效安全地收集资料?

在企业的日常运营与对外合作中,「文件收集」是一项特别常见的文档协作需求。例如,公司举办项目经验分享大会,组织者需要提前收集演讲者的材料;新项目启动时,项目经理需要快速收集技术方案和报价方案以便招投标和商务活…...

用Unity创造自己的绿洲

“谢谢你能玩我的游戏!” 希望将来我也能做出一款影响全世界的游戏,就比如现在的《英雄联盟》,或是电影里的《绿洲》!然后也说出这么一句话:谢谢你能玩我的游戏! 阶段性的总结一下 那就展示一下最近完成的…...

服务器数据恢复—KVM虚拟机被误删除如何恢复虚拟磁盘文件?

服务器数据恢复环境&故障: 1台服务器,Linux操作系统EXT4文件系统,部署了数台KVM虚拟机,每台虚拟机包含一个qcow2格式的磁盘文件,和一个raw格式的磁盘文件。 工作人员操作失误删除了3台服务器上的KVM虚拟机&#xf…...

工具清单 - 看板工具

# 工具清单 Crepido在新窗口打开 - Create (kanban) boards to track users and projects from flat markdown files. MIT NodejsKanboard在新窗口打开 - Simple and open source visual task board. (Source Code在新窗口打开) MIT PHPmyTinyTodo在新窗口打开 - Simple way t…...

Go微服务: 分布式之发送带有事务消息的示例

分布式之发送带有事务消息 现在做一个RocketMQ的事务消息的 demo 1 )生产者 package mainimport ("context""fmt""time""github.com/apache/rocketmq-client-go/v2""github.com/apache/rocketmq-client-go/v2/prim…...

【go】go初始化命令总结

包初始化 test项目目录下执行 go mod init test go mod tidy生成二进制可执行文件 go build -o test .\main.go...

vue音乐播放条

先看效果 再看代码 <template><div class"footer-player z-30 flex items-center p-2"><div v-if"isShow" class"h-12 w-60 overflow-hidden"><div :style"activeStyle" class"open-detail-control-wrap&…...

halcon实现浓淡补正,中间值补正-抽取暗

代码效果 抽取前 中值抽取暗 halcon函数代码 测试图片参数 NoiseCut:16 Gain:1 输入ImagePart NoiseCut Gain *获取直方图 get_domain (ImagePart, Domain) gray_histo_range(Domain,ImagePart,0,255,256, Histo, BinSize) area_center(Domain, NumPixels, Row, Column) …...

太速科技-FMC213V3-基于FMC兼容1.8V IO的Full Camera Link 输入子卡

FMC213V3-基于FMC兼容1.8V IO的Full Camera Link 输入子卡 一、板卡概述 该板卡为了考虑兼容1.8V电平IO&#xff0c;适配Virtex7&#xff0c;Kintex Ultrascale&#xff0c;Virtex ultrasacle FPGA而特制&#xff0c;如果要兼容原来的3.3V 也可以修改硬件参数。板卡支持1路…...

GPU短缺和模型效率的推动

1. 引言 随着全球GPU短缺和云计算成本的不断上升&#xff0c;开发更高效的AI模型成为了当前的焦点。技术如低秩适应&#xff08;LoRA&#xff09;和量化&#xff08;Quantization&#xff09;在优化性能的同时&#xff0c;减少了资源需求。这些技术不仅在当前的AI开发中至关重…...

linux在文件夹中查找文件内容

linux在文件夹中查找文件内容 在Linux中,可以通过以下多个途径,在文件夹中查找文件内容: 1、使用grep命令: grep -r "要查找的内容" /path/to/folder-r参数表示递归地在文件夹及其子文件夹中搜索。/path/to/folder是要搜索的文件夹路径。2、使用ack命令 ack …...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...