Go语言如何实现stop the world?

高可用架构 · · 454 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go语言如何实现stop the world?

Go语言如何实现stop the world?

本文基于 Go 1.13。

在某些垃圾回收器算法中,“停止世界”(Stop the World: STW,下同)是跟踪内存使用最重要的阶段,它会停止程序的执行,以扫描内存使用,并添加写障碍。让我们回顾一下它在内部如何工作,以及它可能面临的潜在问题。

停止世界(Stop the world)

停止程序意味着停止所有正在运行的 goroutine。下面是一个执行 STW 的简单程序:


func main() {
   runtime.GC()
}

运行垃圾回收器,将触发 STW 两个阶段。

有关垃圾回收器周期的更多信息,建议阅读我的另外一篇文章 “Go:垃圾收集器如何标记内存? ① ”

第一步:抢占所有正在运行的 goroutine:
Go语言如何实现stop the world?

goroutine 抢占

一旦 goroutine 被抢占,它们将在安全点停止。同时,P 处理器将(正在运行的代码或在空闲列表)被标记为已停止,以不运行任何代码:
Go语言如何实现stop the world?

P 标记为已停止

然后,Go 调度程序将运行,将每个 M 与其 P 各自分离,并将其放入空闲列表中:
Go语言如何实现stop the world?

M 已移至闲置清单

关于在每个上运行的 goroutine M,它们将在全局队列中等待:
Go语言如何实现stop the world?

Goroutine 在全局队列中等待

然后,一旦世界停止了,只有唯一活动的 goroutine 才能安全地运行,并在工作完成后启动整个世界。下面跟踪图将有助于理解此阶段发生在何时:
Go语言如何实现stop the world?

跟踪 “ STW”阶段

系统调用

“STW”阶段也可能会影响系统调用,因为它们可能会在 STW 时返回。让我们以一个密集执行系统调用的例子,并查看其如何处理:


func main() {
   var wg sync.WaitGroup
   wg.Add(10)
   for i := 0; i < 10; i++ {
      go func() {
         http.Get(`https://httpstat.us/200`)
         wg.Done()
      }()
   }
   wg.Wait()
}

这是跟踪:
Go语言如何实现stop the world?

STW 阶段,系统调用正在结束。但是,由于没有可用 P(如上一节所述,它们都被标记为已停止),goroutine 将被放入全局队列,并在世界恢复时稍后运行。

延迟时间

“STW” 第三步涉及将所有 M 与其 P 分离。但是,Go 将等待它们自行停止:在调度程序运行时,在 syscall 调用中等。等待 goroutine 被抢占应该很快,但是在某些情况下,可能会导致某些延迟。让我们以一个极端的情况为例:


func main() {
   var t int
   for i := 0;i < 20 ;i++  {
      go func() {
         for i := 0;i < 1000000000 ;i++ {
            t++
         }
      }()
   }

   runtime.GC()
}

在这里,“ Stop the World”阶段需要 2.6 秒:
Go语言如何实现stop the world?

没有函数调用的 goroutine 将不会被抢占,并且 P 在任务结束之前不会被释放。这将迫使“STW”等待。有几种解决方案可改善循环中的抢占,有关此方面的更多信息,建议阅读我另外一篇文章“ Go:Goroutine和抢占 ②”。

相关链接:

https://medium.com/a-journey-with-go/go-how-does-the-garbage-collector-mark-the-memory-72cfc12c6976
https://medium.com/a-journey-with-go/go-goroutine-and-preemption-d6bc2aa2f4b7

原文:
https://medium.com/a-journey-with-go/go-how-does-go-stop-the-world-1ffab8bc8846

参考阅读:

  • 关于Golang GC的一些误解--真的比Java算法更领先吗?
  • Swift程序员对Rust印象:内存管理
  • 聊聊一对一沟通的方法
  • 为什么说系统越简单,宕机时间越少

本文作者 Vincent Blanchon,由高可用架构翻译。技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。

高可用架构

改变互联网的构建方式

Go语言如何实现stop the world?


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:高可用架构

查看原文:Go语言如何实现stop the world?

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

454 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传