前陣子對golang中的回收機制突然有興趣,因為golang再回收機制上面我自己在run service時
回收的速度特別有感觸,所以研究了一下,並且稍微紀錄一些小筆記跟大家分享
What is GC?
GC 是Garbage Collection 的簡稱,中文稱為“垃圾回收”。
那在GC裡面什麼定義為“垃圾”?
把分配到堆中那些不能通過程序引用的對象稱為非活動對象,也就是死掉的對象,我們稱為“垃圾”。 |
What is GC doing ?
而GC主要工作就做兩件事情
1.找到內存空間裡的垃圾。 |
Heap And Stack
講到golang如何選擇哪些是”垃圾“,就不免談到 heap 與 stack的關係
簡單來說, stack 在大陸翻譯都叫做“堆”, 而heap 則稱“棧”, 不要問我為什麼因為我也不知道
在這邊就直接以原文來介紹這兩個的關係。
- stack 主要用於靜態記憶體配置,也就是你可以預期收回的空間都會存放於 stack
- heap 則是主要用於動態記憶體配置,是無法預期或者不能確定此空間大小則會放於 heap 上
用此程式碼來介紹說, 在StudentRegister中 我new了一個Student struct 的空間, 但因為在這個情況下, 程式會認為這個宣告沒有一個明確的收回以及空間的宣告,這時就會將這個s 配置的空間放於heap底下。 p.s. 因為stack能存放的空間是有一定大小的,因此遇到不確定的空間宣告時,程式會將這些空間放在heap 下才不怕記憶體爆炸!! 而另外main再呼叫StudentRegister時,可以明確知道main執行完後就會收回,因此程式則會將他放於stack中
golang 有個方便的參數 `-gcflags=-m` 這參數可以幫我檢查宣告的物件是否跑至heap或存於stack中
If we don’t have GC
如果沒有GC, 工程師們就得自行做內存管理,也就是上面我介紹的你不只要做好stack的回收
並且你也需要將所有跑至heap的空間管理好,否則service 跑著跑著就會記憶體不夠。
這不打緊,更怕的是可能會有收錯的問題,更嚴重可能會有重複宣告空間,講這麼多大概有感覺的GC
的重要了吧。
GC introduction
mark-sweep

- 會先從根路徑往下尋找所有的得達到的節點
- 將這些節點做標記
- 全部標記完後,將會STW(stop the world)
- 將其他沒有標記到的節點做刪除
- Start the world
缺點:
- The larger the memory, the longer the scan.
- Stop The World.
reference counting

- 任何只要一被宣告的空間就給他個一計數器(count)
- 若有人引用此空間count則會加一,反之取消引用則減一
- 當count為0時,代表無人引用,此時即可將空間給收回
缺點:
- Need to refer to the counting field.
- Can not directly deal with ring garbage.
copying

- 會將記憶體分為 from and to 兩個空間
- 當空間不足分配新對象或者定時需要收取時,則會觸發GC,做STW
- 此時就會將所有存活的對象全部複製到to空間下
- 當複製完成後再將from 和 to 的空間互換
缺點:
- Only half of the memory can be used at a time.
- The larger the memory, the longer it will scan and move.
- Pause the app for a long time.
小結
對於各種的GC方式先做個簡單的介紹,之後會再介紹golang使用的GC機制是怎麼樣的
但總歸一句,我能活在GC發明後的時代真是太好了(因為我是個很懶惰的人)!