第 64 期深入淺出 Golang Runtime
文章來自於:https://reading.developerlearning.cn/reading/64-2019-10-24-go-runtime/
分享者:郝以奮 @ 騰訊 NOW 直播
觀看視訊
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
回看視訊
-
Q&A 總結
Q: 騰訊現在用 go 的多嗎?
多, 至少 2000 人的級別了,對 go 的接受度挺高的,使用人數在迅速增加,當然大部分團隊還是 cpp。
Q: 騰訊 NOW 直播 go 開發佔比多少?
我們都是從其他語言轉的,cpp,java->golang,一開始就寫 go 的比較少。基本上學習一下,一個星期就可以開始寫線上 go 服務了。目前新服務都是 go。
Q: 執行緒切換的開銷
執行緒切換大概在幾微秒級別,協程切換大概在百 ns 級別。
執行緒切換過程:
- 進入系統呼叫
- 排程器本身程式碼執行
- 執行緒上下文切換: PC, SP 等暫存器,棧,執行緒相關的一些區域性變數,還涉及一些 cache miss 的情況;
- 退出系統呼叫
協程切換不需要進入和退出系統呼叫, 在進行上下文切換時也更輕量, 只需要切換幾個暫存器, 協程 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 中,使用以下系統呼叫。
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 中。
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 深入淺出 Runtime(一):初識
- 深入淺出 Runtime(三):訊息機制
- 深入淺出 Runtime(六):相關面試題面試題
- 深入淺出 Runtime(四):super 的本質
- 深入淺出 Runtime(二):資料結構資料結構
- 深入淺出 Gin 生命週期
- 深入淺出 Golang 資源嵌入方案:前篇Golang
- 深入淺出FE(十四)深入淺出websocketWeb
- 深入淺出 Golang 資源嵌入方案:go-bindata篇Golang
- 深入淺出爬蟲之道: Python、Golang與GraphQuery的爬蟲PythonGolang
- 一週活動速遞|深入淺出第8期;Meetup成都站報名進行中
- 深入淺出Tomcat/3 - Tomcat生命週期Tomcat
- React16 生命週期函式深入淺出React函式
- 深入淺出——MVCMVC
- 深入淺出mongooseGo
- HTTP深入淺出HTTP
- 深入淺出IO
- 深入淺出 RabbitMQMQ
- 深入淺出PromisePromise
- ArrayList 深入淺出
- mysqldump 深入淺出MySql
- 深入淺出decorator
- 深入淺出 ZooKeeper
- 機器學習深入淺出機器學習
- 深入淺出HTTPHTTP
- http 深入淺出HTTP
- 深入淺出 ARCore
- 深入淺出 synchronizedsynchronized
- 深入淺出WebpackWeb
- 深入淺出 blockBloC
- block深入淺出BloC
- 淺讀-《深入淺出Nodejs》NodeJS
- 第 12 期 golang 中 goroutine 的排程Golang
- 【進階 6-3 期】深入淺出節流函式 throttle函式
- 《深入淺出webpack》有感Web
- 深入淺出 Laravel MacroableLaravelMac
- 反射的深入淺出反射
- Flutter | 深入淺出KeyFlutter