计算机内存地址对齐,深入理解内存对齐
從底層來說,計算機訪問內存的兩種方式:
從為word_size(比如32位或者64位)的倍數的地址開始,
1. 讀取長度為word_size的內存塊的數據,或者
2. 把長度為word_size的數據寫入內存。
這里有兩個“天性”【注釋1】:
1. 讀/寫總是從word_size的倍數的地址開始的(wikipedia上Data Structure Alignment詞條獨獨少了這條至關重要的說明,雖然從其上下文可以推斷出來)
2. 讀/寫的長度總是word_size的倍數
比如在一臺64位的計算機上,讀取一塊1k的內存,CPU需要進行的讀取操作次數是:
基于這兩個天性,內存對齊這個概念,包含兩個方面:
1. 內存塊地址的對齊
指的是內存塊的地址(即一塊內存的首字節的地址)是word_size的倍數;用幾個例子來說明這個意思:
1)在一臺32位計算機上的內存里,某個int型變量i在內存中的地址是0x7B163E00;
2)某個char變量c在內存中的地址是0x7B163D00,等等
內存地址不對齊,會引起什么樣的問題呢?用一個例子來說明:
假定在一臺32位機器上,有一個整型變量i的地址是34 【注釋2】,那i存儲在內存的34、35、36、37地址;
為了把這個變量從內存讀進CPU,由于計算機從內存讀取數據的天性(第一點,讀/寫總是從word_size的倍數的地址開始的),需要兩次讀取(第一次從32開始讀32 33 34 35,第二次從36開始讀36 37 38 39),然后把第一次讀取的后兩個字節(34 35)抽取出來,把第二次讀取的前面兩個字節(36 37)抽取出來拼到一起組成變量i:
� ? ? ? ?一個int變量為4bytes,即32位,從CPU一次可以讀取的內存塊長度來看,本可以一次讀完;但是因為這個變量的內存塊地址沒有對齊,將導致本來一個read指令就能完成的讀取操作,需要兩次read外加其它復雜的抽取拼接計算,從而大大地降低了性能。
2. 內存長度的對齊
指的是某個內存塊里,存的各個數據占的長度總是word_size或者是其倍數;從實際應用來說,這一點不總是�滿足的。比如說有這么一個結構體:
�struct ExampleStruct {
char b;
int ? ?a;
};
結構體ExampleStruct包含兩個數據成員:b(char型)和a(int型);其中a占的內存恰好是word_size,但b占的卻不足word_size【注釋3】;不失一般性,假定char型變量占兩個字節;這個時候,為了使內存對齊,一般會在這個char變量后面“加塞”�兩個字節無意義的數據,使得這個char“占用”的內存和int一樣長,達到word_size,即4字節。
如果不進行這種“加塞”,會引起什么問題呢?同樣,用一個例子來說明:
假定現在有一個ExampleStruct的數組a[2],里面有兩個ExampleStruct的對象a[0], a[1];由于數組的內存在分配的時候相鄰的元素總是在相鄰的內存地址上的,于是a[0]占的內存長度是4 + 2字節等于6字節,假定它從32地址開始,則其在內存中占用的空間為32 33 34 35 36 37;因為a[0]和a[1]連續存儲,于是a[1]占用的內存是38 39 40 41 42 43;從而a[1]的首字節地址為38,不是word_size(即4)的倍數,于是引發1中說到的內存塊地址未對齊時引發的問題。
注釋:
注釋1:天性:與生俱來的特性;這里所說的計算機天性,指的內存訪問(即讀或寫)的方式,是在計算機生產制造的時候就確定并現實了的。
注釋2:此處為簡單起見,不失一般性,使用34這種“人類可讀”的地址,而不再使用0x7B163E00等這種“原生”地址
注釋3:一般來說,現代�編譯器在實現的時候,一個int(整型)的長度,等于目標機器的字長;而char(字符型)一般比int(整型)小。
總結
以上是生活随笔為你收集整理的计算机内存地址对齐,深入理解内存对齐的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: setTimeOut函数传参数
- 下一篇: RobotFramework自动化测试框