广告
返回顶部
首页 > 资讯 > 后端开发 > GO >GoLang内存模型详细讲解
  • 725
分享到

GoLang内存模型详细讲解

GoLang内存模型Go内存模型 2022-12-15 12:12:34 725人浏览 安东尼
摘要

目录栈内存-协程栈-调用栈逃逸分析Go 堆内存堆如何进行分配go 语言对象的垃圾回收如何减少GC对性能的分析GC 优化效率栈内存-协程栈-调用栈 为什么go的栈是在堆上? go 协程

栈内存-协程栈-调用栈

为什么go的栈是在堆上?

go 协程栈的位置: go的协程栈位于go的堆内存,go 的gc 也是对堆上内存进行GC, go堆内存位于操作系统虚拟内存上, 记录局部变量,传递参数和返回值 ,go 使用的参数拷贝传递,如果传递的值比较大 注意传递其指针

go 参数传递 使用 值传递, 也就是说传递结构体时候,拷贝结构体的指针,传递结构体指针时候 拷贝的结构体指针 所以对于 只读参数,不进行修改,最好传递结构体指针

协程栈的空间不够大 怎么办?

本地变量太大,栈帧太多

逃逸分析

不是所有的变量都放在协程栈上,栈帧回收后,需要继续使用的变量,或者 太大的变量,分为指针逃逸,空接口逃逸和大变量逃逸,从栈逃逸分配到堆空间上

指针逃逸 (函数返回的指针被其他使用)

func a() *int {
	v :=0
	return &v // 导致 局部变量会分配在堆行 不会分配栈上
}

空接口逃逸(函数的参数是interface{} 函数的实参很可能会逃逸,主要因为interface{} 类型函数往往会使用反射

fmt.Println(i) // 入参属于interface{} 空接口, 是否有反射查看值是什么类型 逃逸到堆上

大变量逃逸(过大变量导致的空间不足,超过64KB的变量会逃逸)

// 解决协程的栈空间不足

调用栈帧太多(栈扩容)

  • 解决方式 进行栈扩容,Go的栈初始空间为2KB
  • 在函数调用前判断栈空间morestack
  • 早期使用分段栈(go 1.13) 在逻辑上连接,优点没有空间浪费,栈指针会在不连续的空间跳转,后期 连续栈,缺点 伸缩时候开销大,扩容为原来2倍, 使用比例不足1/4, 变为原来的 1/2

go 堆内存

操作系统的虚拟内存:操作系统给应用提供的虚拟的内存的空间,背后也是物理内存或者磁盘

go 使用 heapArena每次申请虚拟内存单元 64MB,所有的heapArena 组成 堆内存

线性分配据或者链表分配出现空间碎片,所有go 语言中使用分级分配,避免内存的碎片化,每个内存进行分级思想, mspan n内存管理单元

按照需求进行分级分配,runtime.sizeclass.go 进行分配, 总共有68 个级别。

其中 136 个span , mcentral 属于链接头,其中 68个需要GC扫描,其他68个不需要GC扫描。 mcentral 的属于中心索引,使用互斥保护,在高并发的场景下 锁冲突严重,参考GMP模型,增加线程的本地缓存

  • Go 模仿TCmalloc ,建立自己的堆内存架构
  • 使用heapArena 向操作系统申请内存,以mspan 为单位,防止碎片化
  • mcentral 是mspan 的中心索引
  • 使用mcache 本地缓存 大大降低 锁竞争问题

堆如何进行分配

  • Tiny 微对象(0,16B)无指针 – 分配到普通mspan(class 1 - class 67) --将多个微级对象合并成16Byte
  • Small 对象[16B, 32K] – 定制作mspan (class 0)
  • Large 大对象(32KB, +)
  • heapArena 不足的化 会自动申请扩容

go 语言对象的垃圾回收

  • 标记-清除
  • 标记-整理 (go 语言使用分级分配 不需要标记整理)
  • 标记-复制 (只有用内存进行复制,但是空间浪费非常大,Java的新生代) 总结: Go 堆内存的独特方式 进行标记清除掉,如何寻找有用?
  • Gc的起点: 1. 被栈上的指针引用 2.被全局变量引用 3.被寄存器中指针引用
  • Root 节点进行广度优先策略进行搜索(可达性分析标记方法)
  • 暂停所有其他协程,进行可达性分析,找到无引用的GC 属于串行GC 属于在OLD version 中

如何减少GC对性能的分析

如何进行并行GC 提升性能?

难点在于如何进行标记阶段,go 语言采用的 三色标记方法

  • 黑色: 表示已经分析扫描,有用
  • 灰色: 有用,还没进行分析扫描 DFS代替队列
  • 白色: 暂时无用

当三色标记结束后只有黑色的对象,下一次开启恢复成 白色

并发标记的问题(删除)-- 在GC时候 进行对象的指针的变动,针对 并发标记问题 使用 Yuasa 删除屏障, 强制将释放的C指针变成灰色,避免 在GC过程中被粗我䣌标记

Yuasa 删除屏障(s释放的指针进行强制为灰色)

1. 删除屏障可以杜绝在GC标记中删除的问题 ,但是也无法解决并发标记的插入问题

针对插入屏障 使用 Dijkstra 插入屏障 并发标记过程中 将C进行强制置灰,当并发标记过程,新指针指向新的对象,新增的依赖对象 防止错误的GC

混合屏障

被删除的堆对象标记成为灰色

被添加的堆对象标记成为灰色

并发垃圾回收关键在于标记安全,兼顾的安全的效率

GC 优化效率

GC触发的时机

系统定时触发

g0 协程内的sysmon 定时检查 ,在2min 内 forcegcperiod 没有过GC,触发,谨慎调整

用户显示触发

调用runtime.gc 并不推荐

申请内存触发

给申请对象的时候伴随着GC

GC优化原则

尽量少在堆上产生垃圾

内存池化(channel 中 环形池)

减少逃逸 (fmt 包, 返回了指针不是拷贝)

使用空结构体 (不占用空结构体,使用channel 传递空结构体)

使用如下的方式 查看内存

$env:GODEBUG="gctrace=1"

到此这篇关于golang内存模型详细讲解的文章就介绍到这了,更多相关Go内存模型内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: GoLang内存模型详细讲解

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

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

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

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

下载Word文档
猜你喜欢
  • GoLang内存模型详细讲解
    目录栈内存-协程栈-调用栈逃逸分析go 堆内存堆如何进行分配go 语言对象的垃圾回收如何减少GC对性能的分析GC 优化效率栈内存-协程栈-调用栈 为什么go的栈是在堆上? go 协程...
    99+
    2022-12-15
    GoLang内存模型 Go内存模型
  • Golang设计模式之原型模式详细讲解
    目录原型模式概念示例原型模式 原型是一种创建型设计模式, 使你能够复制对象, 甚至是复杂对象, 而又无需使代码依赖它们所属的类。 所有的原型类都必须有一个通用的接口, 使得即使在对象...
    99+
    2023-01-11
    Go原型模式 Go设计模式
  • VueMVVM模型超详细讲解
    目录理解MVVM模型什么是 MVVM 模型MVVM的组成部分Vue中的实现MVVM模型在Vue中的应用理解MVVM模型 我们知道每一个 Vue 应用都是从创建一个新的实例开始的,根据...
    99+
    2022-11-13
    Vue MVVM模型 Vue MVVM框架
  • 【JVM】JVM内存模型(详细)
    目录 一.JVM概述1.jvm简介2.jvm作用3.jvm的内存模型 二.类加载器1.类加载器的作用2.加载器的类型3.双亲委派机制的运行过程4.双亲委派机制优缺点5.为什么要破坏双亲委派机制6.破坏双亲委派机制的方式 三....
    99+
    2023-08-16
    jvm java 面试
  • Golang表示枚举类型的详细讲解
    枚举,是一种重要的数据类型,由一组键值对组成,通常用来在编程语言中充当常量的标识符。在主流行编程语言如 c、 java 等,都有原生支持。在 go 中,大家却找不到 enum 或者...
    99+
    2022-11-12
  • 详细分析Java内存模型
    目录一、为什么要学习并发编程二、为什么需要并发编程三、从物理机中得到启发四、Java 内存模型五、原子性5.1、什么是原子性5.2、如何保证原子性六、可见性6.1、什么是可见性6.2...
    99+
    2022-11-12
  • NodeJs内置模块超详细讲解
    目录一、fs文件系统模块1、fs.readFile()读取文件2、fs.writeFile()写入文件3、fs路径问题二、path路径模块1、path.join()拼接路径2、pat...
    99+
    2023-01-10
    NodeJs内置模块 NodeJs内置模块介绍 NodeJs内置模块有哪些
  • Golang设计模式之单例模式详细讲解
    目录单例模式概念示例单例模式 单例是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。 单例拥有与全局变量相同的优缺点。 尽管它们非常有用, 但...
    99+
    2023-01-11
    Go单例模式 Go设计模式
  • Java 超详细讲解设计模式之原型模式讲解
    目录传统方式原型模式基本介绍原型模式在spring框架中源码分析深入讨论-浅讨论和深拷贝原型模式的注意事项和细节传统方式 克隆羊问题 现在有一只羊 tom,姓名为: tom,年龄为:...
    99+
    2022-11-13
  • 详细讲解Golang请求包
    Golang是一门越来越受欢迎的编程语言,它在服务器端的应用领域日益增多。开发者们都知道,网络请求在服务器端开发中是必不可少的部分,那么Golang中怎么进行网络请求呢?本文将详细讲解Golang请求包,让大家更好地掌握Golang网络请求...
    99+
    2023-05-14
  • Golang设计模式中的桥接模式详细讲解
    目录桥接模式概念示例桥接模式 桥接是一种结构型设计模式, 可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。 层次结构中的第一层 (通常称为抽象部分) 将包含对第二...
    99+
    2023-01-11
    Go桥接模式 Go设计模式
  • Golang设计模式之适配器模式详细讲解
    目录适配器模式概念示例适配器模式 适配器是一种结构型设计模式, 它能使不兼容的对象能够相互合作。 适配器可担任两个对象间的封装器, 它会接收对于一个对象的调用, 并将其转换为另一个对...
    99+
    2023-01-11
    Go适配器模式 Go设计模式
  • Java内存模型的深入讲解
    目录内存模型硬件架构Java内存模型与硬件关联对象的可见性竞争条件总结Java内存模型展示了Java虚拟机是如何与计算机内存交互的,解决多线程读写共享内存时资源访问的问题。 内存模型...
    99+
    2022-11-12
  • Java内存模型详解
    目录什么是JMM主存与工作内存volatile 关键字有什么用一个线程对共享变量做了修改之后,其他的线程能够看到(感知到)该变量的这种修改(变化)什么是JMM JMM全称Java M...
    99+
    2023-05-18
    Java内存模型 Java JMM模型
  • Java——内存模型详解!
    Java内存模型是一种抽象的规则或规范,定义了程序中存在竞争现象的对象(包括实例字段、静态字段和数组对象,不包括局部变量,形式参数;后者是线程私有,不存在竞争问题)的访问方式。         如果我们要想深入了解Java并发编程,就要先理...
    99+
    2023-10-20
    java 开发语言
  • yolov5模型配置yaml文件详细讲解
    目录以models/yolov5s.yaml为例我们一个一个来解释:补充:模型 yaml 文件中第四参数解释总结 yolov5的代码模型构建是通过.yaml文件实现的,初次...
    99+
    2022-11-11
  • Golang设计模式中抽象工厂模式详细讲解
    目录抽象工厂模式概念示例抽象工厂模式 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。 抽象工厂定义了用于创建不同产品的接口, 但将实际的创建工...
    99+
    2023-01-11
    Go抽象工厂模式 Go设计模式
  • C++详细讲解内存管理工具primitives
    目录primitivesnew 和 deleteplacement new重载 operator newper-class allocatorNew Handler=default,...
    99+
    2022-11-13
  • Python超详细讲解内存管理机制
    目录什么是内存管理机制一、引用计数机制二、数据池和缓存什么是内存管理机制 python中创建的对象的时候,首先会去申请内存地址,然后对对象进行初始化,所有对象都会维护在一 个叫做re...
    99+
    2022-11-11
  • Java内存模型JMM详解
    Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性、是否可以重排序等问题的无关具体平台的统一的保证。(可能在术语上与Java运行时内存分布有歧义,后者指堆、方法区、线程栈等内存...
    99+
    2023-05-30
    java 内存模型 详解
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作