【Go 夜读】第 64 期深入浅出 Golang Runtime

yangwen13 · · 671 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

>文章来自于:https://reading.developerlearning.cn/reading/64-2019-10-24-go-runtime/ 分享者:郝以奋@腾讯NOW直播 ## 观看视频 https://youtu.be/oFJL8S1dwsw ## Go 夜读第 64 期深入浅出 Golang Runtime ## 内容简介 本次分享将会对 go runtime 的调度,内存分配,gc 做一些细节上的讲解,同时也需要参与者对 runtime 有一些初步了解。 ## 内容大纲 - Golang Runtime 是什么,其发展历程; - 调度的实质和关键数据结构,函数; - 内存分配中 mspan, mheap, mcentral, mcache 等数据结构 - Golang GC 发展,Golang 三色标记实现的一些细节,元信息,写屏障,1.5 与 1.12 GC 的区别; - 一点优化思路与问题排查思路; - 总结及 question; - 平时我看 runtime 代码的一些方式; ## 分享嘉宾 郝以奋,yifhao, 腾讯 NOW 直播后台开发,负责 NOW 直播 CPP+JAVA 双栈 -> Golang 转型:框架协同建设,业务功能定制,Go Mod 引入,服务模板,RPC 协议 Go Mod 化,服务模板,Golang 培训,文档等。 目前 NOW 直播后台有 300 多个 Go 服务。 ## 分享信息 时间:2019-10-17 21:00:00 ~ 23:10:00, UTC+8 分享 Slides:https://github.com/Frank-Hust/share ## 回看视频 - https://www.bilibili.com/video/av73297683 - https://youtu.be/oFJL8S1dwsw ---- ## Q&A 总结 ### Q: 腾讯现在用go的多吗? 多, 至少 2000 人的级别了,对go的接受度挺高的,使用人数在迅速增加,当然大部分团队还是 cpp。 ### Q: 腾讯 NOW 直播 go 开发占比多少? 我们都是从其他语言转的,cpp,java->golang,一开始就写 go 的比较少。基本上学习一下,一个星期就可以开始写线上 go 服务了。目前新服务都是 go。 ### Q: 线程切换的开销 线程切换大概在几微秒级别,协程切换大概在百 ns 级别。 线程切换过程: 1. 进入系统调用 2. 调度器本身代码执行 3. 线程上下文切换: PC, SP 等寄存器,栈,线程相关的一些局部变量,还涉及一些 cache miss 的情况; 4. 退出系统调用 协程切换不需要进入和退出系统调用, 在进行上下文切换时也更轻量, 只需要切换几个寄存器, 协程 `runtime.g` 结构只有 40 多个字段, 而线程的 task struct 有大概 300 个字段. 可参考进程/线程上下文切换会用掉你多少CPU? https://zhuanlan.zhihu.com/p/79772089 协程究竟比线程能省多少开销? https://zhuanlan.zhihu.com/p/80037638 ### Q: 为啥是边缘触发, 而不是水平触发的方式? 因为网络操作 ready 和未 ready 对于协程来说就是状态的切换。 socket fd ready 了, 阻塞之上的协程就从 waiting 变成 runnable。 操作时 socket fd 未 ready,那协程就从 running 变成 waiting。 假如采取水平触发,如果一个协程因为某个连接读而变成 waiting 状态,这个连接有数据后,与之关联的协程就变成 ready,这个协程一直没去读数据,那水平触发一直就会 poll 出来该 fd,没必要。 ### Q: 内存什么时候释放? 内存释放分两步 没有存活对象的 span 被 GC 回收, 归还到 mheap 结构中,变成 free 的 page。 sysmon 协程会扫描,超过一段时间没有再被使用的 page(1.12 机制有改变), 通过 madvise 系统调用告诉操作系统,这些 page 对应的物理内存不再需要了,可以与虚拟内存解绑,给其他分配使用。 ### Q: 0.1+13+0.3ms 三个时间的意思? `GCDEBUG=gctrace=1` 会打印出 gc 相关的时间,这三个分别代表,gc 开始时第一个 stw 的 wall time, 并发标记的 wall time 以及 GC 标记结束阶段 stw 的 wall time。 ### Q: []byte 于 string 的黑魔法 底层数据共享,减少数据拷贝。 https://jaycechant.info/2019/golang-unsafe-cast-between-string-and-bytes/ ### Q: 之前说的 netpoll,被 gopark 挂起的 G 扔哪了,怎么找到对应的 G,然后又怎么扔给对应的 M 的 runQ 的? 并没有扔哪里去,也没放在哪个队列。 一个协程因为某个网络 fd 的操作阻塞时,会把该 fd 添加到 epoll 中,使用以下系统调用。 ```c int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); typedef union epoll_data { void *ptr; int fd; __uint32_t u32; __uint64_t u64; } epoll_data_t; struct epoll_event { __uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ }; ``` go 在 epoll_event 中的 epoll_data_t 放了一个指针值,该指针指向一个包含 runtime.g 的结构体。 下次 epoll_wait 时,便可把该 epoll_data_t 也 poll 出来,相当于与该 fd 关联的上下文,也就可以找到阻塞其上的协程。 不需要再放回对应的 M 的 runq 中,目前是通过 injectglist 放在全局的 runq 中。 ---

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

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

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