【Go专家编程——内存管理——垃圾回收】

垃圾回收

所谓的垃圾就上不在需要的内存块,垃圾如果不清理,这些内存块就没有办法再次被分配使用。在不支持垃圾回收的编程语言中,这些垃圾内存就上泄露的内存。

1. 垃圾回收算法

常见的垃圾回收算法有3种

  • 引用计数:对每个对象维护一个引用计数,当引用该对象的对象被销毁时,引用计数减1,当引用计数器为0时回收该对象
    • 优点:对象可以很快被回收,不会出现内存耗尽或达到某个阈值时才回收
    • 缺点:不能很好地处理循环引用,实施维护引用计数也有一定的代价
    • 代表语言:Python,PHP,Swift
  • 标记-清除:从根变量开始遍历所有引用的对象,引用的对象标记为"被引用",没有标记的对象被回收
    • 优点:解决了引用计数的缺点
    • 缺点:需要STW,即暂停程序运行
    • 代表语言:Go(三色标记法)
  • 分代收集:按照对象声明周期的长短划分不同的代空间,生命周期长的放入老年代,短的放入新生代,不同代有不同的回收算法和回收频率
    • 优点:回收性能好
    • 缺点:算法复杂
    • 代表语言:Java

2.Go垃圾回收

2.1 垃圾回收的原理

垃圾回收的核心就是标记处那些内存还在使用,哪些内存不再使用了(即未被引用),把未被引用的内存回收,以供后续内存分配使用。

垃圾回收开始时从root对象扫描,把root对象引用的内存标记为“被引用”,考虑到内存块中存放的可能是指针,所以还需要递归地进行标记,全部标记完成后,只保留被标记的内存,未被标记的内存全部标记为未分配即完成了回收。

2.2 内存标记(Mark)

之前的博客有介绍了span数据结构,span中维护了一个个内存块,并有成员变量allocBits表示每个内存块的分配情况。在span的数据结构中还有另一个位图gcmarkBits(之前的文章中未被写出),用于标记内存块被引用的情况。

allocBits和gcmarkBits的数据结构完全一样,标记结束后就上内存回收,回收时将allocBits指向gcmarkBits,代表标记过的内存才是存活的内存,gcmarkBits则会在下次标记时重新分配内存。

2.3 三色标记法

三色对应了垃圾回收过程中对象的三种状态

  • 灰色:对象还在标记队列中等待
  • 黑色:对象已被标记,gcmarkBits对应的位为1(该对象不会再本次GC中被清理)
  • 白色:对象未被标记,gcmarkBits对应的位为0(该对象会在本次GC中被清理)

在这里插入图片描述

  1. 初始化阶段:
    • 所有对象最初都被标记为白色,表示尚未访问。
    • 设置一个根集,根集通常包括当前的栈变量、全局变量以及Go运行时的数据结构等可以直接访问到的对象。这些根集中的对象被标记为灰色。
  2. 并发标记阶段:
    • 从灰色对象开始,垃圾回收器会遍历这些对象引用的所有对象,并将其从白色改为灰色,表示这些对象已被发现但其引用的对象还未被检查。
    • 同时,标记过程会递归进行,每当完成一个对象的引用检查(即将其引用的所有白色对象标记为灰色),该对象就会被标记为黑色,表示该对象及其所有引用链上的可达对象都已被访问过,不会再被重新访问。
    • 这个过程是并发执行的,即垃圾回收器与程序的其他部分并行工作,以减少停顿时间。
  3. 重新扫描(重新标记)阶段:
    • 由于标记阶段是并发进行的,程序可能在此期间修改了某些对象的引用关系,这可能导致一些本应标记为灰色或黑色的对象仍保持为白色。因此,需要有一个阶段来修正这种不一致,这个阶段称为重新扫描或重新标记阶段。
    • 在这个阶段,垃圾回收器会暂停所有非垃圾回收相关的任务,再次检查灰色对象,并确保它们的引用关系已经被正确处理,新发现的白色对象会被标记为灰色继续处理,直至没有灰色对象剩余。
  4. 清理阶段:
    • 当所有可达对象都被标记为黑色后,垃圾回收器知道所有白色对象都是不可达的,可以被安全地回收。
    • 这个阶段会释放那些白色对象占用的内存空间,为新的分配做准备。

STW(Stop Whe World)就是停止所有的goroutine,专心做垃圾回收,待垃圾回收结束后再回复goroutine
STW时间的长短直接影响了应用的执行。

3. 垃圾回收优化

为了缩短STW的时间,Go也在不断地优化垃圾回收算法。

3.1 写屏障(Write Barrier)

  • 写屏障就是让goroutine与GC同时运行的手段,写屏障可以打打缩短STW的时间。
  • 写屏障类似一种开关,在GC的特定时机开启,开启后指针传递时会标记指针,即本轮不回收,下次GC时再确定。
  • GC过程中新分配的内存会被立即标记,用的正是写屏障技术,即GC过程中分配的内存不会再本轮GC中回收

3.2 辅助GC(Mutator Assist)

为了防止内存分配过快,在GC执行过程中,如果goroutine需要分配内存,那么该goroutine会参与一部分GC的工作,即帮组GC做一部分工作,这个机制叫做Mutator Assist。

4. 垃圾回收的触发时机

4.1 内存分配量达到阈值触发GC

每次内存分配时都会检查当前内存分配量是否已达到阈值,如果达到阈值则立即启动GC。
阈值 = 上次GC内存分配量 * 内存增长率
内存增长率由环境变量GOGC控制,默认为100,即每当内存扩大一倍时启动GC

4.2 定期触发GC

默认情况下,最长2分钟触发一次GC。
通过变量forcegcperiod变量中被声明

4.3 手动触发

程序代码中也可以使用使用runtime.GC()来手动触发GC,主要用于GC的性能测试和统计。

5. GC性能优化

  • GC性能与对象数量负相关,对象越多GC性能越差,对程序影响越大。
  • 所以GC性能优化的思路之一就是减少对象分配的个数:比如使用对象复用或使用大对象组合多个小对象
  • 内存逃逸现象会产生一些隐式的内存分配,也有可能成为GC的负担

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue学习笔记3——事件处理

事件处理 1、事件处理器(1)内联事件处理器(2)方法事件处理器 2、事件参数3、事件修饰符 1、事件处理器 我们可以使用v-on 指令(简写为)来监听DOM事件,并在事件触发时执行对应的JavaScript。 用法: v-on:click"me…

牛客NC334 字典序第K小【困难 10叉树 Java/Go/PHP/C++】,力扣 440. 字典序的第K小数字

题目 题目链接: https://www.nowcoder.com/practice/670c2bda374241d7ae06ade60de33e8b https://leetcode.cn/problems/k-th-smallest-in-lexicographical-order/description/ 本答案核心 10叉树, 数学规律Java代码 import java.util.*;public class Solution {…

出题123

题目时限空间说明 无特殊均默认 1 s , 256 M B 1s,256MB 1s,256MB Problem a 最大化 在最大化目标值的基础上选择的操作越多越好,且输出操作应当按照顺序执行,即你的输出顺序就是你的执行顺序,当有多个执行顺序可以最大化目标值时&#xff0…

49 序列化和反序列化

本章重点 理解应用层的作用,初识http协议 理解传输层的作用,深入理解tcp的各项特性和机制 对整个tcp/ip协议有系统的理解 对tcp/ip协议体系下的其他重要协议和技术有一定的了解 学会使用一些网络问题的工具和方法 目录 1.应用层 2.协议概念 3. 网络计…

网络爬虫原理及其应用

你是否想知道Google 和 Bing 等搜索引擎如何收集搜索结果中显示的所有数据。这是因为搜索引擎对其档案中的所有页面建立索引,以便它们可以根据查询返回最相关的结果。网络爬虫使搜索引擎能够处理这个过程。 本文重点介绍了网络爬虫的重要方面、网络爬虫为何重要、其…

Docker学习(3):镜像使用

当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。 一、列出镜像列表 可以使用 docker images 来列出本地主机上的镜像。 各个选项说明: REPOSITORY&am…

vue源码2

vue之mustache库的机理其实是将模板字符串转化为tokens 然后再将 tokens 转化为 dom字符串&#xff0c;如下图 对于一般的将模板字符串转化为dom字符串&#xff0c;这样不能实现复杂的功能 let data {name:小王,age:18 } let templateStr <h1>我叫{{name}},我今年{{ag…

MySQl创建数据库与管理表

创建数据库与管理表 基础知识 完整的数据存储过程 同时&#xff0c;数据库系统层次 数据库服务器 -》 数据库 -》 数据表 -》 行与列 数据库命名规则&#xff1a; 库名、表名不得超过30字符&#xff1b;变量名&#xff08;字段&#xff09;不超过29字符 只能包含A-Z、a-z、…

hive3从入门到精通(二)

第15章:Hive SQL Join连接操作 15-1.Hive Join语法规则 join分类 在Hive中&#xff0c;当下版本3.1.2总共支持6种join语法。分别是&#xff1a; inner join&#xff08;内连接&#xff09;left join&#xff08;左连接&#xff09;right join&#xff08;右连接&#xff09;…

AIGC001-latent-diffusion(SD)第一次让文生图如此生动有趣!

AIGC001-latent-diffusion(SD)第一次让文生图如此生动有趣&#xff01; 文章目录 0 论文工作1 论文方法2 效果 0 论文工作 通过将图像形成过程分解为去噪自编码器的连续应用&#xff0c;扩散模型&#xff08;DMs&#xff09;实现了对图像数据等方面的最先进的综合结果。这些方…

MySQL---通用语法及分类

目录 一、SQL通用语法 二、 SQL分类 1.DDL 1.1 DDL数据库操作 1.2 DDL表操作---查询 1.3 DDL表操作---创建​编辑 1.4 DDL表操作---数据类型 1.5 DDL表操作---修改 1.6 DDL表操作---删除 1.7 DDL总结 2. 图形化界面工具DataGrip 2.1 创建 2.2 使用 3. DML 3.1 DML介绍 3.2 DM…

C语言.数据结构.顺序表

1.顺序表的概念及结构 1.1线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#xff0c;…

Golang net/http标准库常用方法(三)

大家好&#xff0c;针对Go语言 net/http 标准库&#xff0c;将梳理的相关知识点分享给大家~~ 围绕 net/http 标准库相关知识点还有许多章节&#xff0c;请大家多多关注。 文章中代码案例只有关键片段&#xff0c;完整代码请查看github仓库&#xff1a;https://github.com/hltfa…

面试八股之JVM篇3.6——垃圾回收——强引用、弱引用、虚引用、软引用

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

LVS精益价值管理系统 LVS.Web.ashx SQL注入漏洞复现

0x01 产品简介 LVS精益价值管理系统是杭州吉拉科技有限公司研发的一款专注于企业精益化管理和价值流优化的解决方案。该系统通过集成先进的数据分析工具、可视化的价值流映射技术和灵活的流程改善机制,帮助企业实现高效、低耗、高质量的生产和服务。 0x02 漏洞概述 LVS精益…

全国数据库管理系统设计赛-人大金仓内核实训安排正式发布

作为数据库领域国家队&#xff0c;人大金仓积极响应国家战略&#xff0c;通过赛题设计、内核技术支撑及赛前培训等多方面&#xff0c;大力支持全国大学生计算机系统能力大赛-数据库管理系统设计大赛成功举办。目前第二届全国大赛正在火热报名中&#xff0c;各种奖项等你来拿&am…

RabbitMQ 发布订阅

RabbitMQ 发布订阅视频学习地址&#xff1a; 简单模式下RabbitMQ 发布者发布消息 消费者消费消息 Publist/Subscribe 发布订阅 在 RabbitMQ 中&#xff0c;发布订阅模式是一种消息传递方式&#xff0c;其中发送者&#xff08;发布者&#xff09;不会将消息直接发送到特 定的…

Linux文本处理三剑客(详解)

一、文本三剑客是什么&#xff1f; 1. 对于接触过Linux操作系统的人来说&#xff0c;应该都听过说Linux中的文本三剑客吧&#xff0c;即awk、grep、sed&#xff0c;也是必须要掌握的Linux命令之一&#xff0c;三者都是用来处理文本的&#xff0c;但侧重点各不相同&#xff0c;a…

Docker-镜像迁移的三种方式=>备份恢复公有仓库私有仓库

制作好的镜像要被别人使用&#xff0c;有三种方式&#xff1a; 1.先备份镜像&#xff0c;别人通过u盘或者其它方式拷贝后&#xff0c;再恢复镜像&#xff0c;这种方式比较麻烦 2.将制作的镜像上传到公共镜像仓库&#xff0c;被别人拉取后使用&#xff0c;但可能存在网络不通畅或…

嵩山为什么称为三水之源

三水指黄河、淮河、济河&#xff0c;这三条河流环绕在嵩山周边。 黄河横亘在嵩山北部&#xff0c;其支流伊洛河从西南方环绕嵩山&#xff0c;然后汇入黄河。济河&#xff0c;古称济水&#xff0c;源自济源王屋山&#xff0c;自身河道在东晋时代被黄河夺占&#xff0c;从此消失。…