深入探索 Go 语言的编译器与垃圾回收机制
Go 编译器
Go 编译器是通过 go 工具执行的,这个工具的功能不仅仅是生成可执行文件。你可以使用 go tool compile
命令来编译一个 Go 源文件。这个操作将生成一个目标文件,也就是 .o
后缀的文件。以下是在 macOS Mojave 系统上执行的命令和结果展示:
$ go tool compile unsafe.go
$ ls -l unsafe.o
-rw-r--r-- 1 mtsouk staff 6926 Jan 22 21:39 unsafe.o
$ file unsafe.o
unsafe.o: current ar archive
目标文件是一种包含机器代码的文件,通常是不可直接执行的。它的一个主要优势在于在链接阶段所需的内存更少。如果你使用 -pack
命令行参数,go tool compile
会生成一个归档文件,而不是目标文件:
$ go tool compile -pack unsafe.go
$ ls -l unsafe.a
-rw-r--r-- 1 mtsouk staff 6926 Jan 22 21:40 unsafe.a
$ file unsafe.a
unsafe.a: current ar archive
归档文件是一种二进制文件,包含一个或多个文件,主要用于将多个文件合并为一个文件。ar
是其中一种格式,Go 使用的就是这种格式。这个示例中的 unsafe.go
文件不包含任何特殊代码,以上的命令适用于任何有效的 Go 源文件。
查看归档文件内容
你可以使用以下命令查看 .a
归档文件的内容:
$ ar t unsafe.a
__.PKGDEF
_go_.o
-race
标志
另一个值得一提的 go tool compile
命令行参数是 -race
,它可以检测竞态条件。在并发编程中,竞态条件可能导致意想不到的错误。你可以通过以下命令生成汇编语言的输出:
$ go tool compile -S unsafe.go
这个命令会生成大量的输出,虽然它难以理解,但这意味着 Go 编译器很好地隐藏了复杂性,除非你主动要求查看这些细节。
垃圾回收
垃圾回收(GC)是释放未被使用的内存空间的过程,换句话说,GC 会找到那些已经超出作用范围且无法再被引用的对象,并释放它们占用的内存空间。这个过程是在 Go 程序运行时以并发方式执行的,而不是在程序执行前或执行后才开始。Go 垃圾回收的官方文档中提到:
“GC 与变更线程并发运行,精确类型化(也称为精确),允许多个 GC 线程并行运行。它是并发标记-清除,使用写屏障,非代际且非压缩。分配采用大小分离的每 P 分配区,以最小化碎片化,同时在常见情况下消除锁。”
其中涉及到许多术语,接下来我们会逐一解释。首先,我会展示一个查看垃圾回收过程参数的方法。
使用标准库查看垃圾回收参数
幸运的是,Go 标准库提供了一些函数,可以帮助我们了解垃圾回收的运行方式。下面的代码展示了如何获取垃圾回收的相关信息:
package mainimport ("fmt""runtime""time"
)func printStats(mem runtime.MemStats) {runtime.ReadMemStats(&mem)fmt.Println("当前内存分配:", mem.Alloc)fmt.Println("内存总分配:", mem.TotalAlloc)fmt.Println("堆内存分配:", mem.HeapAlloc)fmt.Println("垃圾回收次数:", mem.NumGC)fmt.Println("-----")
}
每当你需要获取最新的垃圾回收统计信息时,你需要调用 runtime.ReadMemStats()
函数。printStats()
函数用于打印这些信息,以避免重复编写相同的代码。
接下来的部分创建了大量的 Go 切片,以分配大量内存并触发垃圾回收:
func main() {var mem runtime.MemStatsprintStats(mem)for i := 0; i < 10; i++ {s := make([]byte, 50000000)if s == nil {fmt.Println("操作失败!")}printStats(mem)}
}
最后一部分代码做了更多的内存分配操作:
for i := 0; i < 10; i++ {s := make([]byte, 100000000)if s == nil {fmt.Println("操作失败!")}time.Sleep(5 * time.Second)
}
printStats(mem)
运行上述代码的输出如下(以 macOS Mojave 为例):
$ go run gColl.go
当前内存分配: 66024
内存总分配: 66024
堆内存分配: 66024
垃圾回收次数: 0
-----
当前内存分配: 50078496
内存总分配: 500117056
堆内存分配: 50078496
垃圾回收次数: 10
-----
当前内存分配: 76712
内存总分配: 1500199904
堆内存分配: 76712
垃圾回收次数: 20
-----
深入理解垃圾回收
观察垃圾回收的行为能够帮助你在性能较慢的应用中发现问题。你可以通过以下命令查看更详细的 GC 信息:
$ GODEBUG=gctrace=1 go run gColl.go
输出会显示每次垃圾回收的详细数据。例如:
gc 4 @0.025s 0%: 0.002+0.065+0.018 ms clock, 47->47->0 MB, 48 MB goal
三色标记-清除算法
Go 的垃圾回收基于三色标记-清除算法。这个算法将堆中的对象分为三类:白色、灰色和黑色。白色对象是垃圾回收的候选对象,而灰色对象可能指向白色对象,黑色对象则不会指向白色对象。
当垃圾回收开始时,所有对象最初是白色的,垃圾回收器会将根对象标记为灰色,并继续扫描灰色对象。如果灰色对象指向白色对象,它会将这些白色对象标记为灰色,最终所有不可达的白色对象会被回收。
在程序运行过程中,如果某个对象变得可达,写屏障机制会将其重新标记为灰色,确保其不会被错误回收。
这个三色标记-清除算法不仅适用于 Go,还可以应用于其他编程语言。
相关文章:
深入探索 Go 语言的编译器与垃圾回收机制
Go 编译器 Go 编译器是通过 go 工具执行的,这个工具的功能不仅仅是生成可执行文件。你可以使用 go tool compile 命令来编译一个 Go 源文件。这个操作将生成一个目标文件,也就是 .o 后缀的文件。以下是在 macOS Mojave 系统上执行的命令和结果展示&…...

2024国赛数学建模-模拟火算法(MATLAB 实现)
模拟退火算法 1.1 算法原理 模拟退火算法的基本思想是从一给定解开始 ,从邻域 中随机产生另一个解 ,接受 Metropolis准则允许目标函数在 有限范围内变坏 ,它由一控制参数 t决定 ,其作用类似于物 理过程中的温度 T,对于控制参数的每一取值 ,算法持续进 行“产生 —判断 —接受…...
YOLOv8 只检测人 只画框不要标签
参考了这个:YOLOv8只检测人(或其他一种或者多种类别)_yolov8只检测指定类别-CSDN博客 1. 只检测人:predict的时候指定参数classes[0] 2. 只画框不要标签:plot的时候传入labelsFalse 3. 标签中去掉置信度:…...

如何将网络安全防范游戏化
组织对威胁的准备和恢复能力跟不上网络犯罪分子的进步。 一些首席执行官仍然认为网络安全需要偶尔干预,而不是持续关注。 但对于许多公司来说,情况并非如此;网络威胁准备需要协调一致的培训工作,因此网络安全团队在攻击发生时已…...

Qt QGraphicsView实现图片放缩、鼠标拖动移动、鼠标点位置放大缩小_图片查看
QtQGraphicsView实现图片放缩、鼠标拖动移动、鼠标点位置放大缩小 头文件: #ifndef TIMGWIDGET_H #define TIMGWIDGET_H#include <QGraphicsItem> #include <QMainWindow> #include <QObject> #include <QWidget>// class TImgWidget : pu…...

Percona Toolkit 神器全攻略(复制类)
Percona Toolkit 神器全攻略(复制类) Percona Toolkit 神器全攻略系列共八篇,前文回顾: 前文回顾Percona Toolkit 神器全攻略Percona Toolkit 神器全攻略(实用类)Percona Toolkit 神器全攻略(配…...
SQLite3 数据类型深入全面讲解
SQLite3,作为一款轻量级的数据库管理系统,在数据存储方面展现出了其独特的魅力。它不仅支持标准的SQL语法,还提供了丰富的数据类型供开发者选择。这些数据类型不仅涵盖了基本的数值和文本类型,还包括了日期时间、二进制数据等复杂…...
Python高效实现Trie(前缀树)及其插入和查找操作
Python高效实现Trie(前缀树)及其插入和查找操作 在Python面试中,考官通常会关注候选人的编程能力、问题解决能力以及对Python语言特性的理解。Trie(前缀树)是一种高效的数据结构,广泛应用于字符串处理、自动补全、拼写检查等场景。本文将详细介绍如何实现一个Trie,并提…...

傅里叶变换家族
禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码...

深度学习——强化学习算法介绍
强化学习算法介绍 强化学习讨论的问题是一个智能体(agent) 怎么在一个复杂不确定的环境(environment)里面去极大化它能获得的奖励。 强化学习和监督学习 强化学习有这个试错探索(trial-and-error exploration),它需要通过探索环境来获取对环境的理解。强化学习 ag…...

轴承知识大全,详细介绍(附3D图纸免费下载)
轴承一般由内圈、外圈、滚动体和保持架组成。对于密封轴承,再加上润滑剂和密封圈(或防尘盖)。这就是轴承的全部组成。 根据轴承使用的工作状况来选用不同类型的轴承,才能更好的发挥轴承的功能,并延长轴承的使用寿命。我…...

【PyTorch】基础环境如何打开
前期安装可以基于这个视频,本文是为了给自己存档如何打开pycharm和jupyter notebookPyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili Pycharm 配置 新建项目的时候选择解释器pytorch-gpu即可。 Jupyte…...
QT教程:QTime和QTimer的使用场景
QTime类 QTime 是一个用来表示和操作时间的类,它处理一天中的具体时间(例如小时、分钟、秒、毫秒)。通常用于计算时间间隔、记录时间戳、获取当前时间等。 特点和功能 表示时间:QTime 用来表示一天中的某个具体时间(小…...
MySQL 迁移中 explicit_defaults_for_timestamp 参数影响
前言 最近在做数据迁移的时候,使用的是云平台自带的同步工具,在预检查阶段,当时报错 explicit_defaults_for_timestamp 参数在目标端为 off 建议修改 on,有什么风险呢?在此记录下。 测试对比 MySQL 默认情况下 expl…...

树状数组记录
树状数组(Fenwick Tree)是一种用于维护数组前缀和的数据结构,支持高效的单点更新和区间查询操作。它的查询和更新时间复杂度为 O ( log n ) O(\log n) O(logn),适用于需要频繁更新和查询的场景。 树状数组的基本操作 单点更…...

客户端时间和服务器时间的区别
客户端时间: 服务器向客户端拷贝一份前端内容,客户端通过JS获取时间,这样获取的是客户端时间 服务器时间: 服务器通过java代码获取的时间传输给客户端,这样获取的是服务器时间 当有些时候需要使用客户端时间…...

已入职华为!!关于我成功拿下华为大模型算法岗经验总结
方向:大模型算法工程师 整个面试持续了1小时10分钟,能够看出面试官是典型搞技术的,问的很专业又很细,全程感觉压力好大,面完后感觉丝丝凉意,不过幸好还是成功拿下了Offer 一面: 自我介绍 简历项目深度交流 1.项目的背…...

从安卓开发到AI产品经理——我的AI绘画之旅
大家好,我是一名有着多年安卓开发经验的程序员。在日复一日的编码生活中,我对AI行业产生了浓厚的兴趣。于是,我决定转行成为一名AI产品经理。在这个过程中,我通过学习AI绘画工具初步了解了AI行业,下面我将分享我的学习…...
代码随想录八股训练营第三十四天| C++
前言 一、vector和list的区别? 1.1.存储方式: 1.2.随机访问: 1.3.插入和删除操作: 1.4.内存使用: 1.5.容量和大小: 1.6.迭代器类型: 1.7.用途: 二、vector 底层原理和扩容过…...
《深入理解 Java 中的 this 关键字》
目录 一、this关键字的基本理解 二、this调用属性和方法 (一)一般情况 (二)特殊情况 三、this调用构造器 四、案例分析 (一)Account类 (二)Customer类 (三&…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
6.计算机网络核心知识点精要手册
计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法:数据与控制信息的结构或格式,如同语言中的语法规则语义:控制信息的具体含义和响应方式,规定通信双方"说什么"同步:事件执行的顺序与时序…...

构建Docker镜像的Dockerfile文件详解
文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...