2018年7月19日 星期四

Go記憶體管理 - 一個簡單範例所引發的探索

今年六月初的文章, 作者為了 Vilnius Go Meetup 所準備的分享, 蠻早就看到了這篇, 會 queue 到現在的主因在於文章末段並沒有回答開頭提出的問題: 為何一個簡單的 Go http server 範例記憶體使用會高達 380MB? 原以為近期可能會寫續章, 可惜的是等了一個半月沒有下文. 然而若細看了昨天所分享的 “Getting to Go” , 這個問題就不難推敲可能的因素, 因此就分享呼應昨日分享的 Go Garbage Collection 相關文章.
這篇內容值得推荐的地方在於, 為了弄清楚相關問題,把從 CPU 方面的 page management, OS 如何管理記憶體, 一路到 Process 內 Heap 與 Stack 的使用都做了交代. 是不錯的從做中學的範例, 另外提供了對系統整體性與層次上的了解.
文章大概在中間開始才開始進入重點, 藉由介紹 Memory Allocators (TCMalloc, ptmalloc2) 切入, 觸及到 Go Memory Allocator 對於記憶體管理上的行為, 說明 Go 是如何處理 tiny object,以及透過 mcache, mheap 與 mspan 三者與 runtime 中負責 OS 層的 mcentral 做記憶體的配置與管理.
文章末段,透過觀察了 runtime 的消耗, C 語言程式的基本用量, 系統關於 process 的資訊 (/proc, /proc/PID/maps), 以及與更簡單的 Go 程式相較.
若有稍微閱讀昨日分享的 “Getting to Go” 可能會聯想到一件事 — stacks of goroutine.使用了 Go routine 一般會有 100K+ 的 stack 的數量, 若平均一個 stack 只要有 4KB 的配置, 就可以消耗 > 400MB, 那麼要確認的就是 Go package 中 http server 是否使用了 goroutine? 查詢 Go 官方文件可以看到:
Serve accepts incoming HTTP connections on the listener l, creating a new service goroutine for each
這說明了 go http 套件中 server 實作上使用了 goroutine 來處理相關的 request.

沒有留言:

在 ARM 平台上使用 Function Multi-Versioning (FMV) - 以使用 Android NDK 為例

Function Multi-Versioning (FMV) 過往的 CPU 發展歷程中, x86 平台由於因應各種應用需求的提出, 而陸陸續續加入了不同的指令集, 此外也可能因為針對市場做等級區隔, 支援的數量與種類也不等. 在 Linux 平台上這些 CPU 資訊可以透過...