写点什么

Go 运行时:4 年之后

  • 2022-10-11
    北京
  • 本文字数:1884 字

    阅读完需:约 6 分钟

Go运行时:4年之后

自 2018 年以来,Go GC,以及更广泛的 Go 运行时,一直在稳步改进。近日,Go社区总结了 4 年来 Go 运行时的一些重要变化。


这些重要变化主要是:

  • sync.Pool 是一种 GC 感知的重用内存的工具,具有较低的延迟影响,并且能够比之前更有效地回收内存。(Go 1.13)

  • Go 运行时能够更主动地将不需要的内存返回给操作系统,减少了内存消耗和出现内存不足的可能性。这将减少最高 20%的空闲内存消耗。(Go 1.13 和 1.14)

  • 在许多情况下,Go 运行时能够更容易地抢占 goroutine,最高可减少 90%的 stop-the-world 延迟。(Go 1.14)

  • Go 运行时能够比以前更有效地管理计时器,特别是在拥有多核 CPU 的机器上。(Go 1.14)

  • 在大多数情况下,现在使用 defer 语句的函数调用的开销与常规函数调用一样少。点击这里观看 Gophercon 2020 的相关演讲。(Go 1.14)

  • 内存分配器的慢路径对 CPU 核心的伸缩性更好,将吞吐量提升了最多 10%,并将尾部延迟降低了最多 30%,特别是在高度并行的程序中。(Go 1.14 和 1.15)

  • Go 内存统计数据现在可以通过更细粒度、更灵活、更高效的 API(runtime/metrics 包)来访问。这将获取运行时统计信息的延迟减少了两个数量级(从毫秒到微秒)。(Go 1.16)

  • Go 调度器在寻找新任务时花费的 CPU 时间减少了 30%。(Go 1.17)

  • Go 代码现在在 amd64、arm64 和 ppc64 上遵循基于寄存器的调用约定,将 CPU 效率提升了最多 15%。(Go 1.17 和 1.18)

  • Go GC 的内部审计和调度已经进行了重新设计,解决了长期存在的各种与效率和健壮性相关的问题。对于 goroutine 占内存使用很大一部分的应用程序来说,这显著降低了应用程序的尾部延迟(最高达 66%)。(Go 1.18)

  • Go GC 现在在应用程序空闲时会限制自己的 CPU 使用。这将空闲应用程序的 GC 周期的 CPU 使用降低了 75%,从而减少可能导致作业调度器混淆的 CPU 峰值。(Go 1.19)


这些变化对用户来说大多是看不见的——他们只需要升级 Go,就可以看到他们所熟悉和喜爱的 Go 代码运行得更好了。


一个新的“旋钮”


Go 1.19 带来了一个期待已久的特性,使用这个特性需要做一些额外的工作,但它具备很大的潜力:Go 运行时的软内存限制。


多年来,Go GC 只有一个调优参数——GOGC。GOGC 允许用户在 CPU 开销和内存开销之间做出权衡。多年来,这个“旋钮”为 Go 社区提供了很好的服务,被用在各种各样的场景中。


Go 运行时团队一直不愿意在 Go 运行时中添加新的旋钮,他们的理由很充分——每个新的旋钮代表了配置空间中的一个新的维度,我们需要对其进行测试和维护,而且可能要永远持续下去。旋钮的激增也给 Go 开发人员增加了理解和使用它们的负担,随着旋钮的增多,情况会变得愈加困难。因此,Go 运行时总是倾向于用最小配置实现合理的行为。


那么为什么要添加内存限制旋钮呢?


内存不像 CPU 时间那么具有可互换性。对于 CPU 时间,如果稍等片刻,将来总会得到更多的 CPU 时间。但对于内存,你所拥有的总是有限的。


内存限制解决了两个问题。


首先,当应用程序的内存使用峰值不可预测时,仅靠 GOGC 几乎无法防止内存被耗尽。如果只使用 GOGC,Go 运行时根本不知道它有多少可用的内存。通过设置内存限制,运行时能够意识到什么时候需要更努力地工作以减少内存开销,从而使运行时能够健壮地应对瞬时的、可恢复的负载峰值。


第二是为了避免不使用内存限制时出现的内存不足。我们必须根据内存峰值调优 GOGC,而为了保持较低的内存开销会导致更高的 GC CPU 开销,即使应用程序没有处于内存使用峰值且有足够的可用内存。这在容器化的环境中尤其重要。在容器化的环境中,程序被部署在具有独立预留内存的容器中。设置内存限制可以为峰值负载提供保护,并可以针对 CPU 开销更主动地调优 GOGC。


内存限制的设计旨在易用性和健壮性。例如,它是对应用程序中 Go 部分的整个内存占用的限制,而不仅仅是 Go 的堆,因此用户不需要额外计算 Go 运行时的开销。运行时还会根据内存限制调整其内存清除策略,以便在内存出现压力时更主动地将内存返回给操作系统。


虽然内存限制是一个强大的工具,但在使用时仍然要谨慎。其中一个需要注意的地方是,它会让你的程序陷入 GC 抖动状态——在这种状态下,程序运行 GC 的时间过多,导致没有足够的时间来处理其他任务。例如,如果内存限制设置得比程序实际需要的内存少,Go 程序可能会崩溃。以前不太可能出现 GC 抖动,除非显式对 GOGC 进行了大量调优。我们选择让内存耗尽而不是陷入抖动状态,因此作为一种缓解措施,运行时将 GC 限制为总 CPU 时间的 50%,即使这样会超过内存限制。


所有这些都需要慎重考虑,因此,作为这项工作的一部分,我们发布了一个新的 GC 指南,其中包含了交互式可视化的图表,以帮助你们理解 GC 成本以及如何操作它们。


更多可以查看 GC 指南:https://go.dev/doc/gc-guide


原文链接:https://go.dev/blog/go119runtime

2022-10-11 17:355933

评论

发布
暂无评论
发现更多内容

2023面试官常考的前端面试题

loveX001

JavaScript

假如面试官要你手写一个promise

helloworld1024fd

JavaScript

支持30+,这款文档提取工具太好用了!

Jackpop

管理者既要安定内部,也要团结外部

石云升

极客时间 2月月更 技术领导力实战笔记

前端一面高频vue面试题(边面边更)

bb_xiaxia1998

Vue

从技术专家到总经理,在不确定中探索和成长

石云升

极客时间 2月月更 技术领导力实战笔记

能不能手写Vue响应式?前端面试进阶

bb_xiaxia1998

Vue

校招前端必会面试题及答案

loveX001

JavaScript

一道React面试题把我整懵了

beifeng1996

React

从React源码分析看useEffect

goClient1992

React

JavaScript 中获取数组最后一个元素3种方法及性能

devpoint

JavaScript slice 数组操作

构建有参与感的干系人小组指南(译)

Bruce Talk

Scrum 敏捷开发 Agile

一个炫酷的头像悬停效果

南城FE

CSS css3 前端 动画 交互设计

React源码分析8-状态更新的优先级机制

goClient1992

React

高效学 C++|编程实例之计算器

TiAmo

c++ 语言 & 开发 语言设计

前端高频手写面试题指南

helloworld1024fd

JavaScript

React源码分析8-状态更新的优先级机制

goClient1992

React

响应式操作实战

老周聊架构

响应式编程 2月月更

百度前端常见react面试题

beifeng1996

React

JS模块化—CJS&AMD&CMD&ES6-前端面试知识点查漏补缺

loveX001

JavaScript

一天梳理完React所有面试考察知识点

beifeng1996

React

腾讯前端二面手写面试题

helloworld1024fd

JavaScript

为什么字节跳动选择使用 Go 语言?

Jackpop

从0到1:健身房私教预约小程序开发笔记

CC同学

私教预约小程序

【AI技术分享会第8期】EMNLP 2022 小样本学习论文解读来啦!开年直播好礼相送

阿里云大数据AI技术

人工智能 自然语言处理 深度学习

说说Vue响应式系统中的Watcher和Dep的关系-面试进阶

bb_xiaxia1998

Vue

NutUI 4.0 正式发布!

京东科技开发者

CSS GitHub UI 轻量化 企业号 2 月 PK 榜

字节前端二面经典vue面试题(边面边更)

bb_xiaxia1998

Vue

写个JS深拷贝,面试备用

helloworld1024fd

JavaScript

80%的前端开发都答不上来的js异步面试题

loveX001

JavaScript

京东前端高频react面试题集锦

beifeng1996

React

Go运行时:4年之后_语言 & 开发_Michael Knyszek_InfoQ精选文章