面試官:簡單聊聊 Go 逃逸分析?

後端時光發表於2022-04-15

又到了金三銀四的時候,作為一年一跳的胖虎,又準備開始跳槽了,這不他今天又請假來面試了。

“跳跳虎”對於今天的面試還是有點準備的,八股文早從網上下載好了,但就是來得及背完就接到面試邀請了。胖虎心想,“不用慫,人稱八股文選手不是白得的,要是能唬住面試官就多要點。”

面試官:“寫過C/C++的同學都知道,呼叫著名的malloc和new函式可以在堆上分配一塊記憶體,這塊記憶體的使用和銷燬的責任都在程式設計師。一不小心,就會發生記憶體洩露。那你說下Golang 是怎麼處理這個問題的”

胖虎:“Golang 通過逃逸分析,對記憶體管理進行的優化和簡化,它可以決定一個變數是分配到堆還棧上。”

面試官:“那你說下什麼是逃逸分析吧”

胖虎想:“這道題我會啊,準備好了嗎,我要開始裝X了。”

Golang 的逃逸分析,是指編譯器根據程式碼的特徵和生命週期,自動的把變數分配到堆或者是棧上面。

通過優化了記憶體管理機制,解放廣大程式設計師的雙手。讓程式設計師更關注於業務。

注意:Go 在編譯階段確立逃逸,並不是在執行時。

面試官:“那你說下什麼是棧和堆”

胖虎心:“這個也簡單啊”

棧( stack)是系統自動分配空間的,例如我們定義一個 char a;系統會自動在棧上為其開闢空間。而堆(heap)則是程式設計師根據需要自己申請的空間,例如 malloc(10);開闢十個位元組的空間。

先看下記憶體分配圖

棧在記憶體中是從高地址向下分配的,並且連續的,遵循先進後出原則。系統在分配的時候已經確定好了棧的大小空間。棧上面的空間是自動回收的,所以棧上面的資料的生命週期在函式結束後,就被釋放掉了。

堆分配是從低地址向高地址分配的,每次分配的記憶體大小可能不一致,導致了空間是不連續的,這也產生記憶體碎片的原因。由於是程式分配,所以效率相對慢些。而堆上的資料只要程式設計師不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放會造成記憶體洩露。

Go

面試官:“那你說下逃逸分析有什麼好處嗎”

胖虎:“你是十萬個為什麼嗎?”, 但胖虎還是掏出了自己的看家本領。

就像剛開始提到的,Go 語言中記憶體的分配不是有程式設計師自己決定的,而是通過編譯階段確定的分配到何處。這樣有什麼好處呢?沒錯機智的你,可能已經猜到了就是為了優化程式,榨乾機器效能,讓記憶體能夠得到更高的使用效率。

通過逃逸分析,那些不需要分配到堆上的變數直接分配到棧上,堆上的變數少了不但同時減少 GC 的壓力,還減輕了記憶體分配的開銷。

面試官點點頭,稱讚的眼光看著胖虎說:“那你在說說,常見的逃逸現象有哪些吧”

胖虎內心崩潰了:“就我一個人一直在這說,都要渴死了,倒是給我來杯水啊,能不能讓我喘口氣”。但一想 JD 上面給的薪資還是挺誘惑人的,那就在回答一題。

func(函式型別)資料型別

package main

import "fmt"

func main() {

    name := test()

    fmt.Println(name())

}


func test() func() string {

    return func() string {

    return "後端時光"

    }
}

執行命令

go build -gcflags="-m -l" eee.go

-m:表示記憶體分析 -l:表示防止內聯優化
結果如下,第11行變數 name 逃逸到了堆上

interface{} 資料型別

package main


import "fmt"


func main() {
    name := "Golang"
    fmt.Println(name)
}

同理執行逃逸分析,結果如下, name 變數也逃逸到堆上了

原因是 go/src/fmt/print.go 檔案中 Println 傳引數型別 interface{}, 編譯器對傳入的變數型別未知,所有統一處理分配到了堆上面去了。

指標型別

package main


import "fmt"


func main() {
    name := point()
    fmt.Println(*name)
}


func point() *string {
    name := "指標"
    return &name
}

結果如下,第11行變數 name 逃逸到了堆上

還有其他情況出現變數逃逸嗎?

“額,這……”,胖虎心想:時間太匆忙了,八股文我就背了這麼點啊,其他的還麼來得及看呢,要是昨天少玩一把遊戲就好了。這可怎麼辦?

看著胖虎憋的滿臉通紅,面試官笑呵呵的說,“沒事的,時間也不早了,今天先到這吧,你還有什麼要問我的嗎?”

胖虎:“還有哪些會出現變數逃逸啊”

面試官:“channel 或者棧空間不足逃逸, 也會導致逃逸的情況,還有其他問題嗎?”

胖虎:“你們雙休嗎?”

面試官:“是的,我們雙休,不過是一個月休息兩天”

胖虎:“啊。”

你們說胖虎還要繼續面試下去嗎?這樣的公司能入職嗎?

文章首發於公眾號
微信搜尋公眾號[ 後端時光 ]
你必須非常努力,才能看起來毫不費力!一起學習成長 !

本作品採用《CC 協議》,轉載必須註明作者和本文連結
關注微信公眾號:後端時光

相關文章