成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Stack vs Heap:棧區分配內存快還是堆區分配內存快 ?

存儲 存儲架構
棧區是自動管理的,堆區是手動管理的,顯然在棧區上分配內存要比在堆區上更快,當在棧區上申請的內存使用場景有限,程序員申請內存時還要更多的依靠堆區,但是在棧區申請的內存滿足要求的情況我個人更傾向于使用棧區內存。

大家好,我是小風哥。

后臺有讀者問到底是從棧上分配內存快還是從堆上分配內存快,這是個比較基礎的問題,今天就來聊一聊。

棧區的內存申請與釋放

毫無疑問,顯然從棧上分配內存更快,因為從棧上分配內存僅僅就是棧指針的移動而已,這是什么意思呢?什么叫做“棧指針的移動”?以x86平臺為例,在棧上分配內存是怎樣實現的呢?很簡單,就一行指令:

sub $0x40,%rsp

這行代碼就叫做“棧指針的移動”,其本質就是這張圖:

很簡單,寄存器esp中保存的是當前棧的棧頂地址,由于棧的增長方向是從高地址到低地址,因此增大棧時需要將棧指針向下移動,即sub指令的作用,這條指令將棧頂指針向下移動了64字節(0x40),因此可以說在棧上分配了64字節。

可以看到,在棧上分配內存其實非常非常簡單,簡單到就只有一條機器指令。

而棧區的內存釋放也非常簡單,也是只需要一條機器指令:

leave

leave指令的作用是將?;焚x值給esp,這樣棧指針指向上一個棧幀的棧頂,然后pop出ebp,這樣ebp就指向上一個棧幀的棧底:

看到了吧,執行完leave指令后ebp以及esp就指向上一個棧幀了,這就相當于棧幀的彈出,pop,這樣stack 1占用的內存就無效了,沒有任何用處了,顯然這就是我們常說的內存回收,因此簡單的一條leave指令就可以回收掉棧區中的內存。

關于棧、棧幀與棧區,更詳細的講解可以參考我寫的這篇《??函數運行時在內存中是什么樣子???》。

接下來我們看到堆區的內存申請與釋放。

堆區的內存申請與釋放

與棧區分配內存相對的是堆內存分配,堆區分配內存有多復雜呢?

在堆區上申請與釋放內存是一個相對復雜的過程,因為堆本身是需要程序員(內存分配器實現者)自己管理的,而棧是編譯器來維護的,堆區的維護同樣涉及內存的分配與釋放,但這里的內存分配與釋放顯然不會像棧區那樣簡單,一句話,這里是按需進行內存的分配與釋放,本質在于堆區中每一塊被分配出去的內存其生命周期都不一樣,這是由程序員決定的,我傾向于把內存動態分配釋放想象成去停車場找停車位。

這顯然會讓問題復雜起來,我們必須小心的維護哪些內存是已經分配出去的以及哪些是空閑的、該怎樣找到一塊空閑的內存、該怎樣回收程序員不需要的內存塊、同時還不能有嚴重的內存碎片問題,棧區分配釋放內存都無需關心這些問題,于此同時當堆區內存空間不足時還需要擴大堆區等等,這些都使得在堆區申請內存要比在棧區分配內存復雜的多。

說了這么多,那么在堆區上申請內存要比在棧上申請內存慢多少呢?

接下來我們寫段代碼實驗一下。

show me the code

void test_on_stack() {
int a = 10;
}

void test_on_heap() {
int* a = (int*)malloc(sizeof(int));
*a = 10;
free(a);
}

void test() {
auto begin = GetTimeStampInUs();
for (int i = 0; i < 100000000; ++i) {
test_on_stack();
}
cout<<"test on stack "<<((GetTimeStampInUs() - begin) / 1000000.0)<<endl;

begin = GetTimeStampInUs();
for (int i = 0; i < 100000000; ++i) {
test_on_heap();
}
cout<<"test on heap "<<((GetTimeStampInUs() - begin) / 1000000.0)<<endl;
}

這段代碼非常簡單,這里有兩個函數:

  • test_on_stack函數中定義一個局部變量,這就是從棧上申請一個整數大小的內存空間
  • test_on_heap函數從堆上申請一個整數大小的內存空間

然后我們在測試函數中分別調用這兩個函數,每一個調用1億次,記錄下需要運行的時間,得到的測試結果為:

test on stack 0.191008
test on heap 20.0215

可以看到,在棧上總耗時只有大概0.2s,而在堆上分配的耗時為20s,相差百倍。

值得注意的是,這里在編譯程序時沒有開啟編譯優化,開啟編譯優化后的耗時是這樣的:

test on stack 0.033521
test on heap 0.039294

可以看到,相差無幾,可這是為什么呢?顯然從常理推斷在棧上分配要更快一些,問題會出在哪里呢?

既然我們開啟了編譯優化,那是不是優化后的代碼運行的更快了呢,我們來看下編譯優化后生成的指令都有啥:

test_on_stackv:
400f85: 55 push %rbp
400f86: 48 89 e5 mov %rsp,%rbp
400f89: 5d pop %rbp
400f8a: c3 retq

test_on_heapv:
400f8b: 55 push %rbp
400f8c: 48 89 e5 mov %rsp,%rbp
400f8f: 5d pop %rbp
400f90: c3 retq

啊哈,編譯器實在是太聰明了,它顯然注意到這兩個函數中的代碼實際上啥也沒干,即使我們還專門為變量a賦值為了10,但后續我們根本就沒有用到變量a,因此編譯器給我們生成了一個空函數,上面這些機器指令實際上對應一個空函數。

小風哥反復在這里添加代碼都沒有騙過編譯器,我試圖加大變量a賦值的復雜度,編譯器依然很聰明的生成了一個空函數,反正我是沒有試出來,可見現代編譯器是足夠智能的,生成的機器指令效率很高,關于該怎樣寫出一個更好的benchmark,從而讓我們可以看到在開啟編譯優化的情況下這兩種內存分配方式的對比,歡迎任何對此有心得或者對編譯優化有心得的同學留言。

最后讓我們來看看這兩種內存分配方式的定位。

棧內存與堆內存的差異

首先我們必須意識到,棧是一種先進后出的結構,棧區會隨著函數調用層級的增加而增大,而隨著函數調用完成而減少,因此棧是無需任何“管理”的;與此同時由于棧的這種性質,在棧上申請的內存其生命周期是和函數綁定在一起,當函數調用完成后其占用的棧幀內存將無效,且棧的大小是有限的,你不能在棧上申請過多內存,就像這樣一段C代碼:

void test() {
int b[10000000];
b[1000000] = 10;
}

這段代碼運行起來后會core掉,原因就在于棧區大小是非常有限的,在棧上分配一大塊數據會讓棧撐爆掉,這就是所謂的Stack Overflow:

額。。。不好意思,圖放錯了,應該是這個Stack Overflow:

不好意思,又放錯了,總之你懂得。

而堆則不同,在堆上分配的內存其生命周期是受程序員控制的,程序員決定什么時候申請內存,什么時候釋放內存,因此堆是必須被管理起來的,堆區是一片很廣闊的區域,堆區空間不足時會向操作系統請求擴大堆區從而獲得更多地址空間。

當然,堆區在給程序員更大靈活性的同時需要程序員確保內存在不被使用時釋放掉,否則會內存泄漏,在棧上申請內存則不存這個問題。

總結

棧區是自動管理的,堆區是手動管理的,顯然在棧區上分配內存要比在堆區上更快,當在棧區上申請的內存使用場景有限,程序員申請內存時還要更多的依靠堆區,但是在棧區申請的內存滿足要求的情況我個人更傾向于使用棧區內存。

本文轉載自微信公眾號「碼農的荒島求生」,可以通過以下二維碼關注。轉載本文請聯系碼農的荒島求生公眾號。

責任編輯:武曉燕 來源: 碼農的荒島求生
相關推薦

2009-06-03 15:52:34

堆內存棧內存Java內存分配

2013-05-17 15:38:22

iOS開發iOS堆棧heap stack

2021-03-22 11:51:22

Java內存棧上

2022-05-05 10:00:53

Kafka分區分配Linux

2021-07-14 10:00:32

Python內存測量

2020-05-27 21:13:27

JavaJVM內存

2021-02-28 13:22:54

Java內存代碼

2017-03-01 10:45:39

Linux驅動技術內存申請

2010-09-25 14:12:50

Java內存分配

2010-09-17 16:14:22

Java內存分配

2010-09-25 15:40:52

配置JVM內存

2021-04-23 07:27:31

內存分配CPU

2013-10-12 13:01:51

Linux運維內存管理

2021-12-16 06:52:33

C語言內存分配

2011-07-15 01:10:13

C++內存分配

2022-01-13 10:30:21

C語言內存動態

2018-02-08 14:57:22

對象內存分配

2022-03-07 10:54:34

內存Linux

2023-10-18 13:31:00

Linux內存

2025-07-01 02:25:00

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天操天天射天天 | 一区二区三区四区av | 欧美三级视频 | 日韩在线免费观看视频 | yeyeav| 精品九九 | 国产四虎| 免费成人av网站 | 欧美电影在线观看网站 | 久久精品国产一区二区电影 | 激情91| 精品一区欧美 | 欧美日韩一区在线 | 久久精品免费观看 | 亚洲成人一级 | 久久久精 | 成人在线精品 | 精品一区二区视频 | 欧洲一级毛片 | 国产传媒毛片精品视频第一次 | 国产四虎 | 精品免费国产一区二区三区四区介绍 | 日韩电影一区 | 国产一区二区在线免费观看 | 伊人超碰 | 国产精品毛片一区二区在线看 | 综合精品 | 亚洲欧美日韩精品久久亚洲区 | 在线观看国产精品一区二区 | 日韩日韩日韩日韩日韩日韩日韩 | 黄色av观看 | 亚洲午夜精品视频 | 一区二区av | 亚洲国产一区二区三区在线观看 | 99福利视频 | 中文字幕一区二区三区在线视频 | 国产91在线 | 亚洲 | 免费看淫片 | 天堂综合网久久 | 日韩成人中文字幕 | 国产一区二区自拍 |