国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Go內(nèi)存分配和逃逸分析-實踐總結(jié)篇

開發(fā) 后端
與棧不同的是,堆區(qū)的內(nèi)存一般由編譯器和工程師自己共同進行管理分配,交給 Runtime GC 來釋放。在堆上分配時,必須找到一塊足夠大的內(nèi)存來存放新的變量數(shù)據(jù)。后續(xù)釋放時,垃圾回收器掃描堆空間尋找不再被使用的對象。

前言

大家好,我是陽哥。

上期內(nèi)容給大家分享了:??Go內(nèi)存分配和逃逸分析-理論篇??

這期內(nèi)容帶大家理論聯(lián)系實踐,詳解Go逃逸分析的場景,我還找到了一個非常好用的在線協(xié)作工具,大家可以直接在線調(diào)試:?https://1024code.com/codecubes/biY4K3l

效果如下:

圖片

要搞清楚GO的逃逸分析一定要先搞清楚內(nèi)存分配和堆棧:

內(nèi)存既可以分配到堆中,也可以分配到棧中。

GO語言是如何進行內(nèi)存分配的呢?其設(shè)計初衷和實現(xiàn)原理是什么呢?

要搞清楚上面的問題,我們先來聊一下內(nèi)存管理和堆、棧的知識點:

內(nèi)存管理

內(nèi)存管理主要包括兩個動作:分配與釋放。逃逸分析就是服務(wù)于內(nèi)存分配的,而內(nèi)存的釋放由GC負責。

在Go語言中,棧的內(nèi)存是由編譯器自動進行分配和釋放的,棧區(qū)往往存儲著函數(shù)參數(shù)、局部變量和調(diào)用函數(shù)幀,它們隨著函數(shù)的創(chuàng)建而分配,隨著函數(shù)的退出而銷毀。

Go應(yīng)用程序運行時,每個 goroutine 都維護著一個自己的棧區(qū),這個棧區(qū)只能自己使用不能被其他 goroutine 使用。棧是調(diào)用棧(call stack)的簡稱。一個棧通常又包含了許多棧幀(stack frame),它描述的是函數(shù)之間的調(diào)用關(guān)系

與棧不同的是,堆區(qū)的內(nèi)存一般由編譯器和工程師自己共同進行管理分配,交給 Runtime GC 來釋放。在堆上分配時,必須找到一塊足夠大的內(nèi)存來存放新的變量數(shù)據(jù)。后續(xù)釋放時,垃圾回收器掃描堆空間尋找不再被使用的對象。

我們可以簡單理解為:我們用GO語言開發(fā)過程中,要考慮的內(nèi)存管理只是針對堆內(nèi)存而言的。

程序在運行期間可以主動從堆上申請內(nèi)存,這些內(nèi)存通過Go的內(nèi)存分配器分配,并由垃圾收集器回收。

為了方便大家理解,我們再從以下角度對比一下堆棧:

堆和棧的對比

加鎖

  • 棧不需要加鎖:每個goroutine都獨享自己的棧空間,這就意味著棧上的內(nèi)存操作是不需要加鎖的。
  • 堆有時需要加鎖:堆上的內(nèi)存,有時需要加鎖防止多線程沖突

延伸知識點:為什么堆上的內(nèi)存有時需要加鎖?而不是一直需要加鎖呢?

因為Go的內(nèi)存分配策略學(xué)習(xí)了TCMalloc的線程緩存思想,他為每個處理器分配了一個mcache,注意:從mcache分配內(nèi)存也是無鎖的。

關(guān)注我,后面帶大家詳解這部分知識點。

性能

  • 棧內(nèi)存管理 性能好:棧上的內(nèi)存,它的分配與釋放非常高效的。簡單地說,它只需要兩個CPU指令:一個是分配入棧,另外一個是棧內(nèi)釋放。只需要借助于棧相關(guān)寄存器即可完成。
  • 堆內(nèi)存管理 性能差:對于程序堆上的內(nèi)存回收,還需要有標記清除階段,例如Go采用的三色標記法。

緩存策略

  • 棧緩存性能更好
  • 堆緩存性能較差

原因是:棧內(nèi)存能更好地利用CPU的緩存策略,因為棧空間相較于堆來說是更連續(xù)的。

下面就介紹今天的重頭戲了:

逃逸分析

上面說了這么多堆和棧的知識點,目的是為了讓大家更好的理解逃逸分析。

正如上面講的,相比于把內(nèi)存分配到堆中,分配到棧中優(yōu)勢更明顯。

Go語言也是這么做的:Go編譯器會盡可能將變量分配到到棧上。

但是,在函數(shù)返回后無法證明變量未被引用,則該變量將被分配到堆上,該變量不隨函數(shù)棧的回收而回收。以此避免懸掛指針(dangling pointer)的問題。

另外,如果局部變量占用內(nèi)存非常大,也會將其分配在堆上。

Go是如何確定內(nèi)存是分配到棧上還是堆上的呢?

答案就是:逃逸分析。

編譯器通過逃逸分析技術(shù)去選擇堆或者棧,逃逸分析的基本思想如下:檢查變量的生命周期是否是完全可知的,如果通過檢查,則在棧上分配。否則,就是所謂的逃逸,必須在堆上進行分配。

逃逸分析原則

Go語言雖然沒有明確說明逃逸分析原則,但是有以下幾點準則,是可以參考的。

  • 不同于JAVA JVM的運行時逃逸分析,Go的逃逸分析是在編譯期完成的:編譯期無法確定的參數(shù)類型必定放到堆中;
  • 如果變量在函數(shù)外部存在引用,則必定放在堆中;
  • 如果變量占用內(nèi)存較大時,則優(yōu)先放到堆中;
  • 如果變量在函數(shù)外部沒有引用,則優(yōu)先放到棧中;

逃逸分析舉例

我們使用這個命令來查看逃逸分析的結(jié)果:go build -gcflags '-m -m -l'

1.參數(shù)是interface類型

package main

import "fmt"

func main() {
a := 666
fmt.Println(a)
}

運行結(jié)果

圖片

原因分析

因為Println(a ...interface{})的參數(shù)是interface{}類型,編譯期無法確定其具體的參數(shù)類型,所以內(nèi)存分配到堆中。

圖片

2. 變量在函數(shù)外部有引用

package main

func test() *int {
a := 10
return &a
}

func main() {
_ = test()
}

運行結(jié)果

圖片

原因分析

變量a在函數(shù)外部存在引用。

我們來分析一下執(zhí)行過程:當函數(shù)執(zhí)行完畢,對應(yīng)的棧幀就被銷毀,但是引用已經(jīng)被返回到函數(shù)之外。如果這時外部通過引用地址取值,雖然地址還在,但是這塊內(nèi)存已經(jīng)被釋放回收了,這就是非法內(nèi)存。

為了避免上述非法內(nèi)存的情況,在這種情況下變量的內(nèi)存分配必須分配到堆上。

3. 變量內(nèi)存占用較大

package main

func test() {
a := make([]int, 10000, 10000)
for i := 0; i < 10000; i++ {
a[i] = i
}
}

func main() {
test()
}

運行結(jié)果

圖片

原因分析

我們定義了一個容量為10000的int類型切片,發(fā)生了逃逸,內(nèi)存分配到了堆上(heap)。

注意看:

我們再簡單修改一下代碼,將切片的容量和長度修改為1,再次查看逃逸分析的結(jié)果,我們發(fā)現(xiàn),沒有發(fā)生逃逸,內(nèi)存默認分類到了棧上。

圖片

所以,當變量占用內(nèi)存較大時,會發(fā)生逃逸分析,將內(nèi)存分配到堆上。

4. 變量大小不確定時

我們再簡單修改一下上面的代碼:

package main

func test() {
l := 1
a := make([]int, l, l)
for i := 0; i < l; i++ {
a[i] = i
}
}

func main() {
test()
}

運行結(jié)果

圖片

原因分析

我們通過控制臺的輸出結(jié)果可以很明顯的看出:發(fā)生了逃逸,分配到了heap堆中。

原因是這樣的:

我們雖然在代碼段中給變量 l 賦值了1,但是編譯期間只能識別到初始化int類型切片時,傳入的長度和容量是變量l,編譯期并不能確定變量l的值,所以發(fā)生了逃逸,會把內(nèi)存分配到堆中。

思考題

好了,我們舉了4個逃逸分析的經(jīng)典案例,相信聰明的你已經(jīng)理解了逃逸分析的作用和發(fā)生逃逸的場景。

我們來想一下,在理解逃逸分析的原理之后,在開發(fā)的過程中如何更好的編碼,進而提高程序的效率,更好的利用內(nèi)存呢?

如何實踐?

理解逃逸分析一定能幫助我們寫出更好的程序。知道變量分配在棧堆之上的差別后,我們就要盡量寫出分配在棧上的代碼。因為堆上的變量變少后,可以減輕內(nèi)存分配的開銷,減小GC的壓力,提高程序的運行速度。

但是我們也要有過猶不及的指導(dǎo)思想。

我認為沒有一成不變的開發(fā)模式,我們一定是在不斷的需求變化,業(yè)務(wù)變化中求得平衡的:

舉個栗子

舉個日常開發(fā)中函數(shù)傳參例子:

有些場景下我們不應(yīng)該傳遞結(jié)構(gòu)體指針,而應(yīng)該直接傳遞結(jié)構(gòu)體。

為什么會這樣呢?雖然直接傳遞結(jié)構(gòu)體需要值拷貝,但是這是在棧上完成的操作,開銷遠比變量逃逸后動態(tài)地在堆上分配內(nèi)存少的多。

當然這種做法不是絕對的,要根據(jù)場景去分析:

  • 如果結(jié)構(gòu)體較大,傳遞結(jié)構(gòu)體指針更合適,因為指針類型相比值類型能節(jié)省大量的內(nèi)存空間
  • 如果結(jié)構(gòu)體較小,傳遞結(jié)構(gòu)體更適合,因為在棧上分配內(nèi)存,可以有效減少GC壓力

總結(jié)

通過本文的介紹,相信你一定加深了堆棧的理解;搞清楚逃逸分析的作用和原理之后能夠指導(dǎo)我們寫出更優(yōu)雅的代碼。

我們在日常開發(fā)中,要根據(jù)實際場景考慮,如何將內(nèi)存盡量分配到棧中,減少GC的壓力,提高性能。

如何找到應(yīng)用開發(fā)效率、程序運行效率、對機器的壓力及負載的平衡點,是程序員進階之旅中的必修課。

本文轉(zhuǎn)載自微信公眾號「 程序員升級打怪之旅」,作者「王中陽Go」,可以通過以下二維碼關(guān)注。

轉(zhuǎn)載本文請聯(lián)系「 程序員升級打怪之旅」公眾號。

責任編輯:武曉燕 來源: 程序員升職加薪之旅
相關(guān)推薦

2023-01-10 09:18:37

Go內(nèi)存分配逃逸

2022-11-30 08:19:15

內(nèi)存分配Go逃逸分析

2021-05-30 19:29:12

內(nèi)存Go語言

2025-09-23 10:08:18

2023-12-22 07:55:38

Go語言分配策略

2022-07-25 15:38:59

Go 語言Go 語言編譯器內(nèi)存逃逸

2024-04-07 11:33:02

Go逃逸分析

2021-10-14 10:22:19

逃逸JVM性能

2022-07-10 23:15:46

Go語言內(nèi)存

2021-01-06 09:47:51

內(nèi)存Go語言

2024-01-31 09:50:10

JVM逃逸分析HotSpot

2021-07-14 10:00:32

Python內(nèi)存測量

2022-11-08 11:26:13

Go逃逸代碼

2020-07-21 14:19:18

JVM編程語言

2017-03-17 09:31:40

2015-11-16 11:22:05

Java對象內(nèi)存分配

2023-11-21 08:03:43

語言架構(gòu)偏移量

2021-09-01 08:58:15

存儲Go 系統(tǒng)

2025-10-30 07:15:00

Go內(nèi)存管理編程

2023-10-18 13:31:00

Linux內(nèi)存
點贊
收藏

51CTO技術(shù)棧公眾號

男女网站在线观看| 国产肥臀一区二区福利视频| 91视频精品在这里| 国产在线观看91一区二区三区| 污视频免费在线看| 国产欧美123| 性欧美办公室18xxxxhd| 亚洲精品大尺度| 黄色精品在线看| 久久免费看少妇高潮| 日韩亚洲精品在线| 国产欧美日韩精品一区二区免费| 快播电影网址老女人久久| 激情小视频在线观看| 欧美黑人又粗又大又爽免费| 日本电影一区二区三区| 国产精品视频资源| 久久网福利资源网站| 精品视频久久久| 欧美精品在线视频| 日本黄网站免费| 2001个疯子在线观看| 国产成人综合美国十次| 最新视频 - x88av| 99在线视频首页| 国产精品第1页| 欧洲美女7788成人免费视频| 中文字幕不卡av| 国产丝袜高跟一区| 欧美成人一区二区三区| 欧美精品 日韩| 色激情天天射综合网| 色婷婷狠狠综合| 亚洲成av人**亚洲成av**| 亚洲精选一二三| 玉足女爽爽91| 亚洲成人av资源| 欧美日韩在线视频一区| 色狠狠综合天天综合综合| 欧美日韩亚洲一区二区| 91国模大尺度私拍在线视频| 欧美日本在线播放| 亚洲成人免费网站| 亚洲а∨天堂久久精品9966| 精品国产乱码久久久久久夜甘婷婷| 在线成人av网站| 欧美日韩aaaaa| 亚洲精品久久在线| 最近免费中文字幕视频2019| 久久国产一区二区三区| 日韩美女在线观看| 97se亚洲综合| 色就是色欧美| 久无码久无码av无码| 97超碰在线资源站| 三级视频在线| 欧美freesex黑人又粗又大| 91久久精品无嫩草影院| 成人看的羞羞网站| 久久狠狠一本精品综合网| 成人黄页毛片网站| 亚洲人成影院在线观看| 制服丝袜亚洲精品中文字幕| 亚洲视频电影图片偷拍一区| 秋霞av国产精品一区| 激情伦成人综合小说| 精品无码国产一区二区三区av| 日本女优天堂99伊人| 日本高清在线观看视频| 深夜激情久久| 日本在线不卡一区| 亚洲欧美日韩一区| 日韩av一区二区在线| 欧美综合激情网| 亚洲欧洲日本国产| 在线免费毛片| 亚洲欧洲二区| 日日噜噜夜夜狠狠视频欧美人 | 99re8这里有精品热视频8在线 | 在线免费观看一区| 午夜精品福利视频| 色阁综合av| 蜜桃视频在线入口www| 欧美一级做一级爱a做片性| 午夜在线a亚洲v天堂网2018| 亚洲视频免费在线观看| 日韩av一区在线观看| 麻豆精品传媒视频| 在线的色视频| 麻豆精品国产| 成人h版在线观看| 亚洲国产精品一区二区久| 99久久综合狠狠综合久久止| 免费涩涩18网站入口| 福利一区视频| 韩国精品免费视频| 欧美日韩一区精品| 91亚洲永久免费精品| 特级毛片在线观看| 欧美国产极品| 国产女人18毛片水真多成人如厕 | 久久99国内| 亚洲男帅同性gay1069| 日韩av不卡在线| 日本超碰在线观看| 日本一区福利在线| 日韩美女视频一区| 亚洲最大的免费| 日本一本a高清免费不卡| 宅男一区二区三区| 无码国模国产在线观看| 欧美军同video69gay| 国产a视频免费观看| 亚洲理论在线| 97国产精品视频人人做人人爱| 欧美r级在线| 亚洲精品你懂的| 最新黄色av网站| 欧美欧美全黄| 国产成人久久久| 欧美日韩美女| 欧美日韩亚洲一区二区三区| 亚洲一区二区三区在线免费观看| 老牛影视精品| 图片区小说区国产精品视频| 97中文字幕在线| 亚洲另类黄色| 国产精品一区av| av综合网站| 亚洲香蕉成视频在线观看| 九义人在线观看完整免费版电视剧| 久久久天堂av| 亚洲一区三区视频在线观看| 亚洲在线久久| 国产精品久久久久久久久久免费 | 欧美日韩在线高清| 成人综合专区| 最近中文字幕mv在线一区二区三区四区| 污黄色在线观看| 一区二区三区日韩欧美精品| 少妇人妻互换不带套| 国产成人在线免费| 日本一区二区三区精品视频| 成人3d动漫在线观看| 欧美精品电影在线| 日韩黄色碟片| 亚洲国产精品99| av在线1区2区| 午夜欧美一区二区三区在线播放| 天堂一区二区三区| 三级欧美韩日大片在线看| 91精品久久久久久久久久久久久久| 24小时成人在线视频| 精品欧美久久久| 麻豆影视在线观看_| 亚洲成人免费电影| 羞羞在线观看网站| 最新中文字幕一区二区三区| 天天激情综合| 日韩欧美aⅴ综合网站发布| 国产小视频在线| 欧美变态口味重另类| 写真福利精品福利在线观看| 亚洲午夜精品久久久久久性色| 欧美精品少妇| 国产精品国产三级国产有无不卡| 六月丁香婷婷在线| 国产精品88888| 日本一区二区三区在线视频| 欧美国产三区| 国产精品一区二区久久精品 | 热久久天天拍国产| 欧美日韩福利视频| 成人网ww555视频免费看| 国内久久精品视频| 中文字幕第50页| 国精产品一区一区三区mba桃花| 国产专区一区二区| 国产精品啊啊啊| 成人免费视频观看视频| 91久久久久| 欧美日韩精品免费看| 亚洲高清电影| 少妇精品久久久久久久久久| 久久久噜噜噜| 日本不卡久久| 青青草精品视频| 一区二区精品免费视频| 国产精品99久| 欧美精品无码一区二区三区| 欧美国产精品一区二区| 三级短视频在线| 一区二区在线看| 男人的天堂在线| 欧美大片日本大片免费观看| 第84页国产精品| 久久久亚洲国产天美传媒修理工| 九一亚洲精品| 精品综合久久| 国产一区二区三区四区五区美女 |