亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一文帶你輕松理解Go中的內(nèi)存逃逸問題

 更新時(shí)間:2023年06月28日 10:06:16   作者:7small7  
這篇文章主要給大家介紹Go中的內(nèi)存逃逸問題,文中通過代碼示例講解的非常詳細(xì),對我們的學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的同學(xué)可以跟著小編一起來學(xué)習(xí)

內(nèi)存逃逸是什么

  • 在程序中,每個(gè)函數(shù)塊都會有自己的內(nèi)存區(qū)域用來存自己的局部變量(內(nèi)存占用少)、返回地址、返回值之類的數(shù)據(jù),這一塊內(nèi)存區(qū)域有特定的結(jié)構(gòu)和尋址方式,尋址起來十分迅速,開銷很少。這一塊內(nèi)存地址稱為棧。
  • 棧是線程級別的,大小在創(chuàng)建的時(shí)候已經(jīng)確定,當(dāng)變量太大的時(shí)候,會"逃逸"到堆上,這種現(xiàn)象稱為內(nèi)存逃逸。
  • 簡單來說,局部變量通過堆分配和回收,就叫內(nèi)存逃逸。

內(nèi)存逃逸危害

  • 堆是一塊沒有特定結(jié)構(gòu),也沒有固定大小的內(nèi)存區(qū)域,可以根據(jù)需要進(jìn)行調(diào)整。
  • 全局變量,內(nèi)存占用較大的局部變量,函數(shù)調(diào)用結(jié)束后不能立刻回收的局部變量都會存在堆里面。
  • 變量在堆上的分配和回收都比在棧上開銷大的多。
  • 對于 go 這種帶 GC 的語言來說,會增加 gc 壓力,同時(shí)也容易造成內(nèi)存碎片。

內(nèi)存逃逸現(xiàn)象

  • 向 channel 發(fā)送指針數(shù)據(jù)。因?yàn)樵诰幾g時(shí),不知道channel中的數(shù)據(jù)會被哪個(gè) goroutine 接收,因此編譯器沒法知道變量什么時(shí)候才會被釋放,因此只能放入堆中。
  • 局部變量在函數(shù)調(diào)用結(jié)束后還被其他地方使用,比如函數(shù)返回局部變量指針或閉包中引用包外的值。因?yàn)樽兞康纳芷诳赡軙^函數(shù)周期,因此只能放入堆中。
  • 在 slice 或 map 中存儲指針。比如 []*string,其后面的數(shù)組可能是在棧上分配的,但其引用的值還是在堆上。
  • 切片擴(kuò)容后長度太大,導(dǎo)致??臻g不足,逃逸到堆上。
  • 在 interface 類型上調(diào)用方法。 在 interface 類型上調(diào)用方法時(shí)會把interface變量使用堆分配, 因?yàn)榉椒ǖ恼嬲龑?shí)現(xiàn)只能在運(yùn)行時(shí)知道。

逃逸分析原則

  • 編譯階段無法確定的參數(shù),會逃逸到堆上;
  • 變量在函數(shù)外部存在引用,會逃逸到堆上;不存在引用,則會繼續(xù)在棧上;
  • 變量占用內(nèi)存較大時(shí),會逃逸到堆上;

內(nèi)存逃逸解決

  • 對于小型的數(shù)據(jù),使用傳值而不是傳指針,避免內(nèi)存逃逸。
  • 避免使用長度不固定的slice切片,在編譯期無法確定切片長度,只能將切片使用堆分配。
  • interface調(diào)用方法會發(fā)生內(nèi)存逃逸,在熱點(diǎn)代碼片段,謹(jǐn)慎使用。
    避免內(nèi)存逃逸需要遵循如下兩個(gè)原則:
  • 指向棧對象上的指針不能被存儲到堆中。
  • 指向棧對象上的指針不能超過該棧對象的聲明周期。

具體案例

參數(shù)為interface類型會逃逸

下面通過舉例,來進(jìn)一步論證逃逸分析的原則,加深一下理解

我們可以使用這個(gè)命令go build -gcflags '-m -m -l' go文件名,來查看逃逸分析的結(jié)果。

func main() {
  num := 1
  fmt.Println(num)
}

原因分析:

func Println(a ...interface{}) (n int, err error),這個(gè)函數(shù)的入?yún)⑹?code>interface類型,編譯階段無法確定其具體的參數(shù)類型,所以內(nèi)存分配到堆上

變量在函數(shù)外部有引用會逃逸

func main() {
  _ = test()
}
func test() *int {
  num := 10
  return &num
}

原因分析:

變量num在函數(shù)外部存在引用,函數(shù)退出時(shí)棧中的內(nèi)存(棧幀)已經(jīng)釋放,但引用已經(jīng)被返回,如果通過引用地址取值,在棧中是取不到值的,所以Go為了避免這個(gè)情況,會將內(nèi)存分配到堆上。

變量占用內(nèi)存較大時(shí)會逃逸

func main() {
  //不會逃逸
  s1 := make([]int, 10, 10)
  for i := 0; i < 10; i++ {
    s1[i] = i
  }
  //會逃逸
  s2 := make([]int, 10000, 10000)
  for i := 0; i < 10000; i++ {
    s2[i] = i
  }
}

原因分析:

切片容量過大時(shí),會產(chǎn)生逃逸,內(nèi)存分配到堆上;容量小時(shí),不會逃逸,內(nèi)存分配依賴在棧上。

變量大小不確定時(shí)會逃逸

func main() {
  num := 10
  s := make([]int, num, num) 
  for i := 0; i < num; i++ {
    s[i] = i
  }
}

原因分析:

切片的長度和容量,雖然通過聲明的變量num來指定了,但在編譯階段是未知的,并不確定num的具體值,所以會逃逸,將內(nèi)存分配到堆上。

到此這篇關(guān)于一文帶你輕松理解Go中的內(nèi)存逃逸問題的文章就介紹到這了,更多相關(guān)Go 內(nèi)存逃逸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang根據(jù)生日計(jì)算星座和屬相實(shí)例

    golang根據(jù)生日計(jì)算星座和屬相實(shí)例

    這篇文章主要為大家介紹了golang根據(jù)生日計(jì)算星座和屬相的示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Go語言fmt庫詳解與應(yīng)用實(shí)例(格式化輸入輸出功能)

    Go語言fmt庫詳解與應(yīng)用實(shí)例(格式化輸入輸出功能)

    fmt庫是Go語言中一個(gè)強(qiáng)大而靈活的庫,提供了豐富的格式化輸入輸出功能,通過本文的介紹和實(shí)例演示,相信你對fmt庫的使用有了更深的理解,感興趣的朋友一起看看吧
    2023-10-10
  • Go語言學(xué)習(xí)之時(shí)間函數(shù)使用詳解

    Go語言學(xué)習(xí)之時(shí)間函數(shù)使用詳解

    這篇文章主要為大家詳細(xì)介紹了Go語言中時(shí)間函數(shù)的使用方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2022-04-04
  • 淺析Golang中Gin框架存在的必要性

    淺析Golang中Gin框架存在的必要性

    在Go語言中,net/http?包提供了一個(gè)強(qiáng)大且靈活的標(biāo)準(zhǔn)HTTP庫,那為什么還出現(xiàn)了像?Gin?這樣的,方便我們構(gòu)建Web應(yīng)用程序的第三方庫,下面就來和大家簡單分析一下
    2023-08-08
  • Golang中文字符串截取函數(shù)實(shí)現(xiàn)原理

    Golang中文字符串截取函數(shù)實(shí)現(xiàn)原理

    在golang中可以通過切片截取一個(gè)數(shù)組或字符串,但是當(dāng)截取的字符串是中文時(shí),可能會出現(xiàn)問題,下面我們來自定義個(gè)函數(shù)解決Golang中文字符串截取問題
    2018-03-03
  • Golang中for循環(huán)遍歷避坑指南

    Golang中for循環(huán)遍歷避坑指南

    這篇文章主要為大家詳細(xì)介紹了Golang中for循環(huán)遍歷會出現(xiàn)的一些小坑以及對應(yīng)的解決辦法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-05-05
  • Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    本文主要介紹了Go語言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • 解決golang post文件時(shí)Content-Type出現(xiàn)的問題

    解決golang post文件時(shí)Content-Type出現(xiàn)的問題

    這篇文章主要介紹了解決golang post文件時(shí)Content-Type出現(xiàn)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • golang封裝一個(gè)執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼

    golang封裝一個(gè)執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼

    在?Go?語言中,您可以使用?os/exec?包來執(zhí)行外部命令,不通過調(diào)用?shell,并且能夠獲得進(jìn)程的退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出,下面給大家分享golang封裝一個(gè)執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)的方法,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Go通用的?MapReduce?工具函數(shù)詳解

    Go通用的?MapReduce?工具函數(shù)詳解

    本文介紹了使用Go語言實(shí)現(xiàn)的MapReduce框架,特別是在AWSS3?SDK的MultiPartUpload功能中的應(yīng)用,包括并發(fā)上傳和錯(cuò)誤處理策略,詳細(xì)解釋了如何通過并發(fā)goroutines提高上傳效率,并通過MapReduce模型優(yōu)化代碼結(jié)構(gòu)和處理流程,感興趣的朋友跟隨小編一起看看吧
    2024-09-09

最新評論