Go语言垃圾回收(GC原理)

1. GC回收机制

1.1 V1.3标记清除法

(1)概述

1.STW暂停

STW(暂停业务逻辑,找出可达和不可达对象)

2.对可达对象做上标记

标记完成之后,对象5和对象6不可达,被GC清除.之后STW结束.

(2).缺点
  • STW :让程序暂停,程序出现卡顿.
  • 标记需要扫描整个heap.
  • 清除数据会产生heap碎片.

1.2 V1.5三色标记法

(1) 概述

1.程序创建起初,全部标记为白色,将所有对象放入白色集合中.

2. 将程序的根节点集合展开,遍历Root Set(非递归形式,只遍历一次).得到灰色节点

3.遍历灰色标记表,将可达的对象从白色标记为灰色,遍历之后的灰色,标记为黑色.

4.循环执行第三步,直到灰色标记标中无任何对象.

5.收集所有白色对象(垃圾)

(2) 缺点

如果三色标记法不被STW保护.

当一个白色对象被黑色对象所引用,且灰色对象与它之间的可达关系的白色对象遭到破坏,就会出现对象丢失的情况.

避免上述情况最简单的方式就是STW.

尽量减少STW对程序性能的损耗

  • 强三色不变式: 强制行的不允许黑色对象引用白色对象.
  • 弱三色不变式: 黑色可以引用白色对象,白色对象存在其它灰色对象对它的引用,或者可达它的链路上游存在灰色对象.

屏障机制实现强弱三色不变式

  • 插入屏障: 在A对象引用B对象的时候,B对象被标记为灰色.(将B挂在A下游,B必须被标记为灰色) 满足强三色不变式(不存在黑色对象引用白色对象的情况了,因为白色会强制变成灰色) 插入屏障不在栈上使用.
添加一个下游对象(当前下游对象slot,新下游对象ptr) {//1标记灰色(新下游对象ptr)//2当前下游对象slot=新下游对象ptr
}

插入屏障流程:

由于并发特性,此刻外界向对象4添加添加对象8,对象1添加对象9.对象4在堆区,即将触发插入屏障机制.

当灰色标记表中为空,准备回收白色标记之前,重新遍历扫描一次栈空间.此时加STW暂停保护栈,防止外界干扰.(这也是插入写屏障的不足,结束时需要STW重新扫描栈,10~100ms).

  • 删除屏障: 被删除的对象,如果自身为灰色或者白色,那么被标记为灰色. 满足弱三色不变式(保护灰色对象到白色对象的路径不会断)
添加下游对象(当前下游对象slot , 新下游对象ptr) {//1if 当前下游对象slot是灰色 || 白色{标记灰色(当前下游对象slot)}//2当前下游对象slot = 新下游对象ptr
}

删除屏障流程:

灰色对象1删除对象5,如果不触发删除写屏障,5-2-3路径与主链路断开,最后均会被当作垃圾清除.

删除写屏障回收精度低,一个对象即使被删除了最后一个指向它的指针,也依旧可以活过这一轮,在下一轮的GC中被清理掉.

1.3 V1.8混合写屏障机制

(1) 概述

具体操作:

  1. GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)
  2. GC期间,任何在栈上创建的新对象,均为黑色.
  3. 被删除的对象标记为灰色.
  4. 被添加的对象标记为灰色.

混合写屏障流程:

1.GG刚开始,默认都为白色.

2.三色标记法,优先扫描全部栈对象,将可达对象均标记为黑.

2. GPM调度模型设计

2.1. GPM

  1. G(goroutine协程):Go协程
  2. P(Processor处理器):包含运行Go代码的必要资源,也有调度go协程的能力
  3. M(machine线程):工作线程,由操作系统调度

P的本地队列存放的是等待运行的G,数量不能超过256G,优先将新创建的G放在P的本地队列中,如果满了会放在全局队列中.

GOMAXPROCS:是在程序启动时创建的,指定P的个数.可以通过环境变量,或者在程序中通过runtime.GOMAXPROCS()来设置.(允许相应个数的go协程在同一时刻并行执行)

Go语言本身限制M的最大量为10000.一般M的个数会略大于P.

2.2. 调度器设计策略

  1. 复用线程:避免频繁的创建,销毁线程.而是对线程复用.
    1. work stealing机制: 当本线程无可运行的G时,尝试从其他线程绑定的P偷取G,而不是销毁线程.
    2. hand off机制: 当本线程因为G进行调用阻塞时,线程将释放绑定的P,将P转移给其他空闲线程执行.
  1. 利用并行: GOMAXPROCS设置P的数量,最多由GOMAXPROCS个线程分布在多个CPU上同时运行.
  2. 抢占:在Go中,一个goroutine最多占用CPU10ms , 防止其他goroutine长期得不到执行.
  3. 全局G队列:当M执行work stealing从其他P中偷不到G时,它可以从全局G队列获取G.

2.3. go func()

  1. 有两个存储G的队列,一个是局部调度器P的本地队列,一个全局队列.新创建的G会先保存在P的本地队列中,如果P的本地队列中已满就会保存在全局的队列中.
  2. G只能运行在M中,一个M必须持有一个P.M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,偷取其他队列的P来执行 .
  3. 一个M调度G执行的过程是一个循环机制.
  4. 当M执行某一个G时候如果发生了syscall或其余阻塞操作,M会阻塞,如果当前有一些G在执行,runtime会把这个线程M从P中摘除,然后再创建一个新的操作系统的线程(如果有空闲的线程可用就复用空闲线程)来服务这个P.
  5. 当M系统调用结束后,这个G会尝试获取一个空闲的P执行;并放入到这个P的本地队列.如果获取不到P,那么这个线程M变成休眠状态,加入到空闲线程中,然后这个G会被放入全局队列中.

2.4. 调度器的生命周期

M0:启动程序后的编号为0的主线程.在全局变量runtime.m0中,不需要再heap上分配.负责执行初始化操作和启动第一个G.启动第一个G之后,M0就和其他M一样了.

G0:每次启动一个M,第一个创建的gourtine,仅用于负责调度的G,不指向任何可执行的函数.在调度或系统调用时,会使用M切换到G0来调度.

2.5. 补充

自旋线程会不断的寻找G(优先寻找全局队列中的G)

从全局队列到P本地队列的负载均衡:从全局队列取的个数: n = min(len(GQ) / GOMAXPROCS + 1 , len(GQ)/2)

GQ:全局队列的总长度

偷取另一个P本地队列中的G: 将要偷取的P中的本地队列一分为二,偷取后一半的G.

自旋线程的最大限制: 自旋线程+执行线程 <= GOMAXPROCS

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/847397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用的linux命令

工作中常用的linux命令 查看磁盘存储情况 df -h查看端口占用情况 netstat -tunlp | grep 端口号查看java服务运行情况 ps -ef | grep "java"查看运行内存使用情况 free -h清除内存中的缓存 echo 3 > /proc/sys/vm/drop_caches查看linux系统最大进程数 ulim…

前端面试题日常练-day50 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 1. 在Bootstrap中&#xff0c;以下哪个类用于创建一个具有响应式的图片&#xff1f; a) .img-responsive b) .responsive-img c) .responsive-image d) .image-fluid 2. 哪个Bootstrap类用于创建一…

YYDS练手 130道python练习题 完整版PDF

近年来&#xff0c;Python在编程语言界里赚足了风头&#xff0c;无论是受欢迎程度&#xff0c;还是薪资待遇&#xff0c;都非常可观&#xff0c;相应的&#xff0c;Python岗位要求也越来越高&#xff0c;无论你是零基础还是老前辈&#xff0c;在Python面试中都不能轻视。 不打…

Spring Boot 系统学习第五天:Spring循环依赖实战经验

1 概述 本篇主要介绍使用依赖注入的一些实战经验。 2 把握Bean的作用域 前面说到Setter方法注入时&#xff0c;提到了Spring中的Bean作用域的概念。作用域描述了Bean在Spring IoC容器上下文中的生命周期和可见性。现在讨论Spring框架中不同类型的Bean作用域及其在使用上的指导…

Java 枚举类型深入解析

在Java中&#xff0c;枚举&#xff08;enum&#xff09;是一种特殊的数据类型&#xff0c;它允许一个变量是预定义的常量集合中的一个值。枚举类型在许多场景中都非常有用&#xff0c;比如定义一组明确的常量、简化代码的可读性和维护性等。本文将详细讲解Java中的枚举类型&…

对比WPF和Avalonia的边框渲染差异

众所周知&#xff0c;诸如Border、Rectangle等元素&#xff0c;是具有边框的。但在WPF和Avalonia中&#xff0c;边框的渲染机制有所不同。 如下代码&#xff0c;Border的边框和背景色均为黑色&#xff0c;并且将透明度设为0.5&#xff1a; <Border Width"100" H…

模拟实现C++vector

一&#xff1a;C库中对于vector的介绍 vector的底层其实就是数据结构中的顺序表&#xff0c;顺序表的底层就是变长数组&#xff0c;是一段连续的物理空间 在下面的实现中&#xff0c;重点实现的是其中的迭代器和插入删除&#xff0c;下标访问等功能&#xff0c;模拟实现模板类…

BottomSheetDialog高度自适应,布局RecyclerView使用问题

public class CultureBottomDialogView {/*** 标题*/private static TextView textTitle;/*** 关闭按钮*/private static TextView textClose;/*** 列表*/private static RecyclerView recyclerView;private static BottomDialogAdapter dialogAdapter;private static List<…

15-JavaScript 中的 `call`、`apply` 和 `bind`

JavaScript 中的 call、apply 和 bind 笔记分享 在 JavaScript 中&#xff0c;函数作为一等公民&#xff0c;可以像其他对象一样被操作。这种特性使得我们可以通过特定的方法来控制函数的调用环境&#xff08;即 this 的值&#xff09;。call、apply 和 bind 是三个常用的方法…

消息队列RabbitMQ

1. 消息队列概述 1.1 什么是消息队列 消息队列是一种用于在分布式系统中传递消息的数据结构。它采用先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的方式进行数据存储和管理。消息队列能够解耦生产者和消费者&#xff0c;从而实现系统的松散耦合&#…

Flutter 视频播放利器:Chewie 的介绍与使用

在移动应用开发中&#xff0c;视频播放功能是常见的需求之一。Flutter 作为跨平台开发框架&#xff0c;其生态系统中有许多用于视频播放的插件。其中&#xff0c;Chewie 是一个非常受欢迎且功能强大的视频播放器插件&#xff0c;它是对官方 video_player 插件的包装&#xff0c…

Vue中使用vuex进行全局数据共享处理

1、简介 在之前的博文中&#xff0c;介绍了如何进行组件之间的数据传递&#xff0c;但是对于所有组件共享的变量来说&#xff0c;使用组件之间的数据传递实现复杂&#xff0c;因此本文引入vuex进行全局数据共享。 2、vuex的下载配置 2.1、vuex的下载 # 对于vue2来说&#xf…

第十六章 创建Web客户端 - 修改生成的客户端类

文章目录 第十六章 创建Web客户端 - 修改生成的客户端类修改生成的客户端类调整生成的类以处理极长的字符串 第十六章 创建Web客户端 - 修改生成的客户端类 修改生成的客户端类 生成 Web 客户端类后&#xff0c;通常不需要编辑该类。相反&#xff0c;可以编写代码来创建 Web …

IP地址开启HTTPS方法

可以使用IP地址申请SSL证书&#xff0c;申请之前必须是公网IP地址&#xff0c;不支持内网IP地址申请。 申请过程需要确定IP地址外网可以访问&#xff0c;这里特别注意只是申请过程中可以访问。访问验证过程必须采取80端口、443端口两者选择1个&#xff0c;不可以用其它端口进行…

下载视频怎么转换MP4?wmv转换mp4,推荐这3种方法

在数字化时代&#xff0c;我们经常需要从网上下载各种视频&#xff0c;但有时候下载的视频并不是我们想要的格式&#xff0c;比如WMV。为了能在更多的设备上播放或进行编辑&#xff0c;我们可能需要将其转换为更通用的MP4格式。 那么&#xff0c;下载的视频如何转换成MP4呢&am…

第三篇 编译器和译码器

实验三 编码器和译码器 3.1 实验目的 上一章节我们学习了简单组合逻辑电路——多路数据选择器&#xff0c;在本章节我们将学习另外一种数字系统中常见的简单组合逻辑电路——编码器和译码器。然后通过一个设计一个简易的计算器让大家进一步巩固FPGA开发的流程和方法。 本节您…

“神经网络之父”和“深度学习鼻祖”Geoffrey Hinton

“神经网络之父”和“深度学习鼻祖”Geoffrey Hinton在神经网络领域数十年如一日的研究&#xff0c;对深度学习的推动和贡献显著。 一、早期贡献与突破 反向传播算法的引入&#xff1a;Hinton是将反向传播&#xff08;Backpropagation&#xff09;算法引入多层神经网络训练的…

【C++进阶】深入STL之vector:构建高效C++程序的基石

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模拟实现string &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之vector &#x1f4d2;1.ve…

网络编程(七)

网络编程&#xff08;七&#xff09; UNIX域套接字&#xff08;本地间进程间通信的技术&#xff09;&#xff08;S文件&#xff09;基于TCP传输基于UDP传输 UNIX域套接字&#xff08;本地间进程间通信的技术&#xff09;&#xff08;S文件&#xff09; socket同样也可以用于本…

OpenCV-绘制虚线

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 功能函数 // 绘制虚线 void DrawDottedLine(cv::Mat &input, cv::Point p1, cv::Point p2, cv::Scalar color, int thickne…