相信絕大多數的人都了解記憶體對齊,都知道變數應該按8位元組去對齊,這樣性能高,但是其最最底層的原理是啥呢? 有的人可能會說,因為高速快取是以8位元組為單位進行的,讀者你很聰明,這是原因之一,但我今天想挖的是更底層一點的原理,讓我們去記憶體的物理構成里找找答案!
記憶體物理結構
前面我們說過記憶體是由chip構成,每個chip內部,是由8個bank組成的,其構造如下圖:

而每一個bank是一個二維平面上的矩陣,前面文章中我們說到過,矩陣中每一個元素中都是保存了1個位元組,也就是8個bit,

記憶體編址方式
那么對于我們在應用程式中記憶體中地址連續的8個位元組,例如0x0000-0x0007,是從位于bank上的呢?直觀感覺,應該是在第一個bank上嗎? 其實不是的,程式員視角看起來連續的地址0x0000-0x0007,實際上位8個bank中的,每一個bank只保存了一個位元組,在物理上,他們并不連續,下圖很好地闡述了實際情況,

你可能想知道這是為什么,原因是電路作業效率,記憶體中的8個bank是可以并行作業的, 如果你想讀取址0x0000-0x0007,每個bank作業一次,拼起來就是你要的資料,IO效率會比較高,但要存在一個bank里,那這個bank只能自己干活,只能串行進行讀取,需要讀8次,這樣速度會慢很多,
結論
所以,記憶體對齊最最底層的原因是記憶體的IO是以8個位元組64bit為單位進行的, 對于64位資料寬度的記憶體,假如cpu也是64位的cpu(現在的計算機基本都是這樣的),每次記憶體IO獲取資料都是從同行同列的8個chip中各自讀取一個位元組拼起來的,從記憶體的0地址開始,0-7位元組的資料可以一次IO讀取出來,8-15位元組的資料也可以一次讀取出來,
再換個例子假如你指定要獲取的是0x0001-0x0008,也是8位元組,但是不是0開頭的,記憶體需要怎么作業呢?沒有好辦法,記憶體只好先作業一次把0x0000-0x0007取出來,然后再把0x0008-0x0015取出來,把兩次的結果都回傳給你, CPU和記憶體IO的硬體限制導致沒辦法一次跨在兩個資料寬度中間進行IO,這樣你的應用程式就會變慢,算是計算機因為你不懂記憶體對齊而給你的一點點懲罰,
擴展1:事實上,編譯和聯結器會自動替開發者對齊記憶體的,盡量幫你保證一個變數不跨列尋址,但是他不能做到十分完美,
擴展2:其實在記憶體硬體層上,還有作業系統層,作業系統還管理了CPU的一級、二級、三級快取,不知道你有沒有印象,我們前面的文章說過高速快取里的Cache Line也是64位元組,它是記憶體IO的整數倍,不會讓記憶體IO浪費,

開發內功修煉之記憶體篇專輯:
- 1.帶你深入理解記憶體對齊最底層原理
- 2.記憶體隨機也比順序訪問慢,帶你深入理解記憶體IO程序
- 3.從DDR到DDR4,記憶體核心頻率其實基本上就沒太大的進步
- 4.實際測驗記憶體在順序IO和隨機IO時的訪問延時差異
- 5.揭穿記憶體廠家“謊言”,實測記憶體帶寬真實表現
- 6.NUMA架構下的記憶體訪問延遲區別!
- 7.PHP7記憶體性能優化的思想精髓
- 8.一次記憶體性能提升的專案實踐
- 9.挑戰Redis單實體記憶體最大極限,“遭遇”NUMA陷阱!
我的公眾號是「開發內功修煉」,在這里我不是單純介紹技術理論,也不只介紹實踐經驗,而是把理論與實踐結合起來,用實踐加深對理論的理解、用理論提高你的技術實踐能力,歡迎你來關注我的公眾號,也請分享給你的好友~~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/198477.html
標籤:其他
上一篇:帶你深入理解記憶體對齊最底層原理
下一篇:華為mate40開賣時間
