重要说明:
- 本文仅记录了个人阅读 go release notes 之后的一些肤浅理解,一定会存在大量的错误。
- 有很多重要的改动没有被列出(可能是因为本人无法理解或者不感兴趣)。
- 切记不要当做 Go release notes 的中文翻译,仅仅是一个小笔记。具体的内容请一定请参考原文说明。
官方 Release Notes:
https://go.dev/doc/go1.x (替换 url 最后的版本号即可)
由于本人是从 Go 1.3/1.4 阶段开始接触 Go 的,因此1.5之前的一些修改就不关注了。
Go 1.5
- GC 改动(消除 stw)。
- 调度器改动(并发度更高)。
- Bootstrapping、移出 C 代码,编译器工具链用 Go(大部分由 C转化而来);移出 6a/6l/6g 等。
- (负面)编译器的速度极大的变慢。
- 在 x86 上面的动态链接特性。
Go 1.6
- 加入了 race detector。
- 编译器前端解析器手写(不使用 yacc)。
- vendoring;挂掉的时候打出所有 routine 堆栈;GC 优化。
Go 1.7
- 编译器后端优化 SSA(针对 64-bit x86),性能提升。
- Toolchain 优化:新的导出格式;编译器和链接器性能提升;更小的二进制输出;
Go 1.8
- Assembler 加入某些 64-bit 机器的新指令。
- 去除 yacc 相关的内容。
- SSA 使用到全部的支持架构上。
- 新的 compiler 前端,用户无感知但是丢后续性能优化非常重要。
- 优化 compiler 和 linker 性能。
- Plugin 的初步支持。
- 优化了 GC 和 defer,以及一些标准库。
Go 1.9
- Package 内并发编译。
- Compiler 和 linker DWARF 信息相关改动。
- ARM assembler
MULA
指令 bug fix。 - 工具 pprof 不需要二进制代码就能够查看各种符号(代码行等)信息;
pprof.Do
;pprof.Label 更新。 - GC only blocks the calling routine.
- 新的 bits 标准库;sync.Map 标准库;
Go 1.10
- Build 时候只按照代码来推断是否需要重新编译(而不是修改时间或者 metadata/build flags)。所以不需要 -a 的编译参数了。
- 和第一条类似,go test 也会正确的 cache 结果。go vet 集成到 go test 调用中。
- 在 pprof 中 blocking 和 mutex 的 profile 文件也自带符号表了。
- Assembler 支持更多的指令(在不同的平台)。
Go 1.11 改动:
- Go mods 首次加入。
- Build 时 cache 默认开启;一些内联函数优化;新引入的包导出格式;switch 的未使用变量检查;
- 链接器支持 AVX512;DEBUG信息优化;默认压缩的DWARF 信息;memprof默认使用 alloc 的 profile;vet 优化;
- Runtime: a sparse heap layout.
- Map 遍历删除和 slice extension 优化。
- 编译器优化:bounds-check and branch elimination, transitive relations;各种看不懂的优化。
Go 1.12
- 后续不支持 binary library.
- Go doc 和 go vet 替代 godoc 和 go tool vet。
- GC 和内存管理相关的优化。
Go 1.13
- 数字表达方式更改。
- go module 默认行为改变;GOPRIVATE环境变量;go get 行为改变;二进制中包含模块版本信息;
- 逃逸分析改进(重写);
- 修改 Error wrapper 写法.
- 默认使用
MADV_FREE
来向 os 释放内存(会导致 RSS 变高)。
Go 1.14
- overlapping interfaces proposal 嵌入 struct 的重名机制。
- 提升 defer 性能到几乎0开销(和直接调用该函数相比)。
- 主流平台上实现 goroutin 的异步抢占?(asynchronously preemptible);系统调用的时候会增加很多 EINTR 需要自己处理。
- CPU 数量很多的情况下,大块内存并行高频分配时候的减少锁竞争优化。
- 各种 timer, tick, wait 的优化,减少锁和上下文切换开销。
- 增加一个 bytes 的 hash 函数。
Go 1.12 - Go 1.14
Go 1.15
- Panic 涉及到的变量如果是基础类型派生的,那么把值打出来。
- SIGSEGV, SIGBUS, SIGFPE 会杀掉进程(如果不显式处理的话)。
- 小对象分配优化(在 cpu core 很多的场景下);small int to interface 优化;已关闭的阻塞/非阻塞 chan 行为统一。
- 生成的 bin 文件比上个版本小 5%(消除一些 GC 和未使用类型的 metadata);
- unsafe.Pointer 和 uintptr 的转换规则修改;在编译参数中加入缓解 Spectre漏洞影响的选项。
- 链接器大优化(效率和内存使用),是通过新设计的 obj 文件格式和并发某些操作阶段的并发执行带来的。
Go 1.16
- 支持 Apple Silicon。
- 默认使用
go.mod
,带来go install
/go get
等一堆工具的用法修改。 - 可以使用
//go:embed
来嵌入各种文件。 - 用于取代
runtime.ReadMemStats
和debug.GCStats
等运行时接口的runtime/metrics
;Debug 参数inittrace=1
检查启动效率; - 内存释放策略又改成了
MADV_DONTNEED
(在之前的 1.13 版本变更为MADV_FREE
)。 - (接上个版本的)链接器后续优化。
- 文件处理和 io 相关的一些修改,集中在
io/fs
。
Go 1.17
-
[]T
可以直接转换为[N]T
了。还有一堆新的 unsafe 指针运算。l := []int{1, 2, 3, 4, 5, 6, 7} al := *(*[5]int)(unsafe.Pointer(&l)) // 错误用法! al2 := *(*[5]int)(unsafe.Pointer(&l[0])) // [1 2 3 4 5] al3 := (*[5]int)(l) // &[1 2 3 4 5]
- 新的Module graph pruning
这个特征应该叫做依赖关系图修剪?我的理解是:
依赖的库中,跟你的项目(main module)无关的那些依赖内容,会在go.mod
中标记为// indirect
,而其他的依赖,被称为require directive
。但是为什么要做么做,没有看明白 - 一堆 go mod 相关的行为变化。
- 一种新的函数调用传参方式(使用寄存代替栈),提高5%的性能,较少2%的执行文件容量。应用在 linux/amd64 等最主流体系上。
Go 1.18
- 试验性质的泛型支持。(能力有限,c++中的泛型也没搞明白,无法描述)
- 修复掉长期未处理的一个bug #8560 (一个特殊场景的声明变量未使用,未被探测到的问题)。
- Fuzzing 支持(貌似是和测试相关的)。
- 一堆 go mod 相关行为变化。
- go workspace 的引入,看起来像是一个IDE 的工程文件。
- gofmt 工具并发。
- go vet 能够更智能的检测到一些代码写法的问题。
- GC 在评估执行频率的时候考虑了不在堆上的资源(例如栈扫描)。
- slice 扩容算法变更(避免突变?)。
- 1.17版本的传参优化应用到大部分平台上。这个优化带来的,可能影响堆栈打印不准确的问题,在1.18中会标记一个
?
符号。 - 编译速度慢 15%,生成代码的执行速度不变。
- Bootstrapping 的时候,优先使用 Go 1.17(之前是 1.4),而且预告了在 Go 1.19 的时候,需要用 Go 1.17。(这里不得不吐槽一下:说好的都用 Go 1.4 bootstrapping 呢?)
Go 1.19
- 最大的修改:内存模型修改(没看懂)。
- 优化了 go doc 输出文档的格式。如果按照规范书写,go doc 可以输出超链接和列表格式的文档。
- unix build constraint(类似宏)
- 一堆工具小修改:build 参数加入(在
-trimpath
的情况下)、go generate、go env FLAG quotes、go list 输出优化和 cache。 - 加了一个 soft memory limit,查了一下其他的人的说法,看起来是为了避免发生 OOM。
- 超大的 int/string switch 情况下使用 jump table 优化。
相关文章
暂无评论...