Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深入探索 Go 语言的编译器与垃圾回收机制

深入探索 Go 语言的编译器与垃圾回收机制

作者头像
蒙娜丽宁
发布于 2024-11-23 07:43:42
发布于 2024-11-23 07:43:42
8800
代码可运行
举报
文章被收录于专栏:极客起源极客起源
运行总次数:0
代码可运行

Go 编译器

Go 编译器是通过 go 工具执行的,这个工具的功能不仅仅是生成可执行文件。你可以使用 go tool compile 命令来编译一个 Go 源文件。这个操作将生成一个目标文件,也就是 .o 后缀的文件。以下是在 macOS Mojave 系统上执行的命令和结果展示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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 会生成一个归档文件,而不是目标文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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 归档文件的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ ar t unsafe.a __.PKGDEF _go_.o 

-race 标志

另一个值得一提的 go tool compile 命令行参数是 -race,它可以检测竞态条件。在并发编程中,竞态条件可能导致意想不到的错误。你可以通过以下命令生成汇编语言的输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go tool compile -S unsafe.go 

这个命令会生成大量的输出,虽然它难以理解,但这意味着 Go 编译器很好地隐藏了复杂性,除非你主动要求查看这些细节。

垃圾回收

垃圾回收(GC)是释放未被使用的内存空间的过程,换句话说,GC 会找到那些已经超出作用范围且无法再被引用的对象,并释放它们占用的内存空间。这个过程是在 Go 程序运行时以并发方式执行的,而不是在程序执行前或执行后才开始。Go 垃圾回收的官方文档中提到:

“GC 与变更线程并发运行,精确类型化(也称为精确),允许多个 GC 线程并行运行。它是并发标记-清除,使用写屏障,非代际且非压缩。分配采用大小分离的每 P 分配区,以最小化碎片化,同时在常见情况下消除锁。”

其中涉及到许多术语,接下来我们会逐一解释。首先,我会展示一个查看垃圾回收过程参数的方法。

使用标准库查看垃圾回收参数

幸运的是,Go 标准库提供了一些函数,可以帮助我们了解垃圾回收的运行方式。下面的代码展示了如何获取垃圾回收的相关信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main  import (    "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 切片,以分配大量内存并触发垃圾回收:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {    var mem runtime.MemStats    printStats(mem)    for i := 0; i < 10; i++ {       s := make([]byte, 50000000)       if s == nil {          fmt.Println("操作失败!")       }       printStats(mem)    } } 

最后一部分代码做了更多的内存分配操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for i := 0; i < 10; i++ {    s := make([]byte, 100000000)    if s == nil {       fmt.Println("操作失败!")    }    time.Sleep(5 * time.Second) } printStats(mem) 

运行上述代码的输出如下(以 macOS Mojave 为例):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go run gColl.go 当前内存分配: 66024 内存总分配: 66024 堆内存分配: 66024 垃圾回收次数: 0 ----- 当前内存分配: 50078496 内存总分配: 500117056 堆内存分配: 50078496 垃圾回收次数: 10 ----- 当前内存分配: 76712 内存总分配: 1500199904 堆内存分配: 76712 垃圾回收次数: 20 ----- 

深入理解垃圾回收

观察垃圾回收的行为能够帮助你在性能较慢的应用中发现问题。你可以通过以下命令查看更详细的 GC 信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ GODEBUG=gctrace=1 go run gColl.go 

输出会显示每次垃圾回收的详细数据。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gc 4 @0.025s 0%: 0.002+0.065+0.018 ms clock, 47->47->0 MB, 48 MB goal 

三色标记-清除算法

Go 的垃圾回收基于三色标记-清除算法。这个算法将堆中的对象分为三类:白色、灰色和黑色。白色对象是垃圾回收的候选对象,而灰色对象可能指向白色对象,黑色对象则不会指向白色对象。

当垃圾回收开始时,所有对象最初是白色的,垃圾回收器会将根对象标记为灰色,并继续扫描灰色对象。如果灰色对象指向白色对象,它会将这些白色对象标记为灰色,最终所有不可达的白色对象会被回收。

在程序运行过程中,如果某个对象变得可达,写屏障机制会将其重新标记为灰色,确保其不会被错误回收。

这个三色标记-清除算法不仅适用于 Go,还可以应用于其他编程语言。

- EOF -

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客起源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Go语言的内存管理和垃圾回收
内存管理是指操作系统或编程语言运行时对内存资源的分配、使用和回收的过程。在Go语言中,内存管理包括堆内存和栈内存的分配与回收。
数字扫地僧
2024/06/24
1710
一文搞懂Go语言垃圾回收机制
垃圾回收(Garbage Collection, GC)是现代编程语言管理内存的核心机制之一。Go语言凭借其高效的并发模型和简洁的内存管理设计,在服务端开发、云计算等领域广受欢迎。这篇文章我就带大家从原理、实现到调优,详细解析Go语言的垃圾回收机制。
闫同学
2025/04/22
1720
Go语言垃圾回收机制详解
Go语言(简称Go)是一种开源编程语言,由Google开发和维护。它以并发支持、垃圾回收和良好的标准库著称。垃圾回收(Garbage Collection,简称GC)是Go语言的一大特性,它使得开发者不必手动管理内存,提高了编程效率和安全性。本文将详细介绍Go语言的垃圾回收机制,包括GC的触发条件、工作原理以及性能优化。
Michel_Rolle
2024/06/22
2.8K0
GO进阶(5) 垃圾回收机制
      编程语言通常会使用手动和自动两种方式管理内存,C、C++ 以及 Rust 等编程语言使用手动的方式管理内存,工程师需要主动申请或者释放内存;而 Python、Ruby、Java 和 Go 等语言使用自动的内存管理系统,一般都是垃圾收集机制。这是Go语言成为高生产力语言的原因之一。将开发者从内存管理中释放出来,让开发者有更多的精力去关注软件设计,而不是底层的内存问题。
黄规速
2023/03/06
1K0
GO进阶(5) 垃圾回收机制
go内存分配与垃圾回收
Golang运行时的内存分配算法主要是 TCMalloc算法。 核心思想就是把内存分为多级管理,从而降低锁的粒度。它将可用的堆内存采用二级分配的方式进行管理:每个线程都会自行维护一个独立的内存池,进行内存分配时优先从该内存池中分配,当内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争。
leobhao
2024/11/29
1530
go内存分配与垃圾回收
浅析 Golang 垃圾回收机制
Google 搜索 Golang GC 排名靠前的文章都讲的不错,从设计到实现,从演进到源码,一应俱全。但是庞杂的信息会给人一种恐惧感,让人望而却步。本文尝试使用较为简单易懂的语言和图像,讲解 Golang 的垃圾回收机制。
郭旭东
2020/12/30
1.9K0
浅析 Golang 垃圾回收机制
Go语言垃圾回收机制剖析
垃圾回收(Garbage Collection,GC) 是Go语言的核心特性之一,是实现内存自动管理的一种形式。golang的自动垃圾回收屏蔽了复杂且容易出错的内存操作,让开发变得更加简单、高效。
windealli
2022/09/15
3K3
Go语言垃圾回收机制剖析
GO GC 垃圾回收机制
垃圾回收(Garbage Collection,简称GC)是编程语言中提供的内存管理功能。
孤烟
2020/09/27
7750
一篇搞懂JAVA与GO垃圾回收
导语 现代高级编程语言管理内存的方式分自动和手动两种。手动管理内存的典型代表是C和C++,编写代码过程中需要主动申请或者释放内存;而 PHP、Java 和 Go等语言使用自动的内存管理系统,由内存分配器和垃圾收集器来代为分配和回收内存,其中垃圾收集器就是我们常说的GC。本文中,笔者将从原理出发,介绍Java和Golang垃圾回收算法,并从原理上对他们做一个对比。 Java垃圾回收 垃圾回收区域及划分 在介绍Java垃圾回收之前,我们需要了解Java的垃圾主要存在于哪个区域。JVM内存运行时区域划分如下图所
腾讯VTeam技术团队
2021/09/18
2K0
「硬核JS」你真的了解垃圾回收机制吗
写在前面 我们知道垃圾回收机制是引擎来做的,JS引擎有很多种(各个浏览器都不同),其垃圾回收机制在一些细节及优化上略有不同,本文我们以一些通用的回收算法作为切入,再由 V8 引擎发展至今对该机制的优化为例(为什么以 V8 为例?因为它市场占有率大 😄),一步一步深入来助我们了解垃圾回收机制,因为只有真正了解垃圾回收机制,后面才能理解内存泄漏的问题以及手动预防和优化 JavaScript 是门魅力无限的语言,关于它的 GC(垃圾回收)方面,你了解多少呢?想来大部分人是因为面试才去看一些面试题从而了解的垃圾
isboyjc
2022/03/28
5110
「硬核JS」你真的了解垃圾回收机制吗
golang 系列:啥是垃圾回收?
golang 的三色标记法虽然没有 java 的内存回收机制成熟,但它细分了回收过程,通过写屏障技术,能和用户程序并发进行,这也一定程度的提高了内存回收速度。
lincoln
2021/08/01
4130
golang 系列:啥是垃圾回收?
自动的内存管理系统实操手册——Golang垃圾回收篇
导语 | 现代高级编程语言管理内存的方式分自动和手动两种。手动管理内存的典型代表是C和C++,编写代码过程中需要主动申请或者释放内存;而PHP、Java 和Go等语言使用自动的内存管理系统,由内存分配器和垃圾收集器来代为分配和回收内存,其中垃圾收集器就是我们常说的GC。上期在《自动的内存管理系统实操手册——Java垃圾回收篇》一文中向大家分享了Java垃圾回收算法,今天腾讯后台开发工程师汪汇接着向大家分享 Golang 垃圾回收算法。 从Go v1.12版本开始,Go使用了非分代的、并发的、基于三色标
腾讯云开发者
2021/08/05
8000
详解gc(垃圾回收)机制(一)
进程在运行时,所操作的内存就是虚拟内存,每个进程之间的虚拟内存互相独立,通过 MMU 内存管理技术再映射到物理内存中,同时,虚拟内存空间块分为:
仙士可
2022/09/13
1K0
详解gc(垃圾回收)机制(一)
Go垃圾回收 1:历史和原理
新老朋友好久不见,我是大彬。今天为大家带来的分享是Go语言垃圾回收,这篇文章筹划的了很久,因为GC也是很强大的一个话题,关于GC已经有很多篇论文还有书籍,想通过一篇文章来介绍Go语言的垃圾回收是困难的,所以决定分几篇文章来完成Go语言垃圾回收的相关话题:
大彬
2019/10/23
2K0
Go垃圾回收 1:历史和原理
JVM垃圾回收机制
对于大多数应用来说,Java 堆(Java Heap)是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块 内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”。堆的大小可以通过参数 –Xms、-Xmx 来指定。
羽毛球初学者
2024/10/12
1150
Go语言的runtime包深入解析
Go语言的runtime包是Go标准库中非常重要的一部分,它包含了与Go运行时系统(包括内存分配、垃圾回收、并发调度等)相关的底层函数和数据结构。理解runtime包的工作机制,有助于开发者更好地优化Go应用程序的性能。
数字扫地僧
2024/07/01
5310
图文结合,白话Go的垃圾回收原理
前面两篇文章介绍了Go语言的内存分配策略以及Go协程动态扩充和收缩栈内存的原理,今天这篇文章我们主要来聊一下内存管理的另外一大块内容:垃圾回收。
KevinYan
2020/11/02
8421
图文结合,白话Go的垃圾回收原理
Golang垃圾回收机制
由于STW会影响程序的性能,因此将步骤3和步骤4的顺序调换,让步骤3的垃圾清除步骤与程序同时进行,能够减小STW的时长。
TomatoCool
2023/07/30
2690
Golang垃圾回收机制
Golang GC 介绍
GC 全称 Garbage Collection,目前主流的垃圾回收算法有两类,分别是追踪式垃圾回收算法(Tracing garbage collection)和引用计数法( Reference counting )。
恋喵大鲤鱼
2024/02/07
7510
Golang GC 介绍
每位 Gopher 都应该了解的 Golang 语言的垃圾回收算法
关于垃圾回收,比较常见的算法有引用计数、标记清除和分代收集。Golang 语言使用的垃圾回收算法是标记清除。本文主要介绍一下 Golang 语言的垃圾回收算法。
frank.
2021/02/07
1.5K0
相关推荐
Go语言的内存管理和垃圾回收
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验