又到了金三銀四的時候,作為一年一跳的胖虎,又準備開始跳槽了,這不他今天又請假來面試了。
“跳跳虎”對於今天的面試還是有點準備的,八股文早從網上下載好了,但就是來得及背完就接到面試邀請了。胖虎心想,“不用慫,人稱八股文選手不是白得的,要是能唬住面試官就多要點。”
面試官:“寫過C/C++的同學都知道,呼叫著名的malloc和new函式可以在堆上分配一塊記憶體,這塊記憶體的使用和銷燬的責任都在程式設計師。一不小心,就會發生記憶體洩露。那你說下Golang 是怎麼處理這個問題的”
胖虎:“Golang 透過逃逸分析,對記憶體管理進行的最佳化和簡化,它可以決定一個變數是分配到堆還棧上。”
面試官:“那你說下什麼是逃逸分析吧”
胖虎想:“這道題我會啊,準備好了嗎,我要開始裝X了。”
Golang 的逃逸分析,是指編譯器根據程式碼的特徵和生命週期,自動的把變數分配到堆或者是棧上面。
透過最佳化了記憶體管理機制,解放廣大程式設計師的雙手。讓程式設計師更關注於業務。
注意:Go 在編譯階段確立逃逸,並不是在執行時。
面試官:“那你說下什麼是棧和堆”
胖虎心:“這個也簡單啊”
棧( stack)是系統自動分配空間的,例如我們定義一個 char a;系統會自動在棧上為其開闢空間。而堆(heap)則是程式設計師根據需要自己申請的空間,例如 malloc(10);開闢十個位元組的空間。
先看下記憶體分配圖
棧在記憶體中是從高地址向下分配的,並且連續的,遵循先進後出原則。系統在分配的時候已經確定好了棧的大小空間。棧上面的空間是自動回收的,所以棧上面的資料的生命週期在函式結束後,就被釋放掉了。
堆分配是從低地址向高地址分配的,每次分配的記憶體大小可能不一致,導致了空間是不連續的,這也產生記憶體碎片的原因。由於是程式分配,所以效率相對慢些。而堆上的資料只要程式設計師不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放會造成記憶體洩露。
面試官:“那你說下逃逸分析有什麼好處嗎”
胖虎:“你是十萬個為什麼嗎?”, 但胖虎還是掏出了自己的看家本領。
就像剛開始提到的,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 協議》,轉載必須註明作者和本文連結