如果像SSD一樣,隨機讀寫還是比連續讀寫慢,那麼頁式虛擬內存管理這層轉換是不是會浪費很大的性能?而且即使沒有頁式內存管理,在BIOS層面上的「物理地址」跟真正的內存條上的存儲單元位置就已經不是連續對應的了,是不是也會浪費性能呢?

如果是一樣的,那麼為什麼同樣是晶體管製成的Flash晶元(SSD)的隨機吞吐量就遠小於連續讀寫?如果說機械硬碟隨機訪問慢是因為需要尋道,SSD是沒有尋道時間的啊,訪問任意一個塊需要的時間應該都是一樣的吧?


謝邀。DRAM隨機讀寫是比連續讀寫要慢,我們來看實際的數據:

AMD和Intel的差距不在本文範圍內,我們暫且忽略。我們專註看第一條,就會發現:

按位元組純隨機讀取延遲 &> 在一個page裡面隨機讀取延遲 &> 順序連續讀取延遲

這是為什麼呢?我們分別來看看:

隨機讀取延遲為什麼高?

不是說好內存是隨機讀取設備嗎?為什麼隨機讀取延遲還會高呢?這裡有兩個原因:Burst讀取Prefetcher

我們知道內存條是有64個Bit的數據線:DQ0-DQ63,共8個位元組。如果讀取某個地方的數據,需要不少步驟(大致):

  1. Precharge。

2. 行有效。RAS#低電平,CAS#高電平。意味著現在行地址有效,同時在A0-A13傳送地址信號,即2^13個Row可以選擇。

3. 列有效。RAS#高電平,CAS#低電平。意味著列地址有效,這時在A0-A13上傳送的是列地址。沒錯,A0-A13是行列共用的,所以每個格子選擇需要有1和2兩步才能唯一確定。

4. 數據讀出或寫入。根據COMMAND進行讀取或者寫入。在選定好小方格後,就已經確定了具體的存儲單元,剩下的事情就是數據通過數據I/O通道(DQ)輸出到內存匯流排上了。

而我們Cache line是64個位元組,那麼每次刷新Cache line是不是要來8次這麼多步驟呢?並不是,有Burst讀取,我們沒用的多餘的Prechange,行列選擇也只要一次,就可以連續讀取8個8位元組數據了,也就是Burst Length(BL)是8。如果我們讀了一半,不需要這麼多,可以用Burst Chop來省電。這樣我們就省了7個CL、tRCD、tRP延遲,總延遲能不下降嗎?

Burst mode十分普遍,幾乎出現在所有需要傳輸數據的地方,大到網路傳輸,小到UPI等等通信,DRAM和SSD都有Burst傳輸。

那麼是不是我不是一個位元組一個位元組讀,而是8個位元組8個位元組讀,隨機和順序就完全一樣呢?也不是,CPU中為了提高性能,有很多預取器(Prefetcher)。Prefetcher種類眾多,有指令的,有數據的,有些Prefetcher對某種work load有用,有些則在某種work load中有反作用。Prefetcher也會讓我們順序讀取比隨機讀取更快,它省了指令流水線的部分時間(想想為什麼)。

為什麼跨page最慢呢?

最後分析一下跨Page隨機比同page隨機慢的原因。跨Page有可能要刷TLB,如果不停切page,則必然大量刷新TLB。TLB刷新會消耗大量的Cycle,這是它最慢的原因。


內存每一個bank只有一個buffer,讀寫都要通過這個buffer來進行,這個buffer只能裝載內存的一行,也叫page。

存在buffer中的行的狀態稱為page opened,而同一bank其他行的狀態稱為page closed。

如果到來的命令正好是訪問當前open狀態的行,那麼這叫page hit,只需要一個cas命令(列選擇,既讀或者寫)即可完成操作。

如果所有行處於close狀態,這叫page miss,需要先發一個ras命令,也叫active命令,行選擇。然後再發cas命令完成操作。

如果當前訪問的行和open狀態的行不是同一行,那麼這叫page conflict。需要先發一個pre-charge命令,關閉當前open的行,然後再ras命令,最後cas命令完成操作。

所以memory controller主要使用兩種page策略,open page 和close page。open page,顧明思議,讀寫後不會立刻進行pre-charge,這種策略對連續地址讀寫方式更友好,但一旦出現page conflict,受到的影響就很明顯。而close page則是每次讀寫後立刻pre-charge,這樣每次到來的命令都是page miss,不會出現page conflict,對隨機讀寫更加友好。

一般來說,連續命令以連續地址操作較多,所以一般性能好優化好的memory controller採用open page方式的占多數,需要對命令進行重排序,再調度,保持同一地址的讀寫順序,pre-charge預測等等優化,還要採取對應的地址映射方式(這塊挺複雜,簡單的說,可以把collum地址映射到地址的低位,採用CS interleave,把bank group和bank地址映射到低位,bank group比bank更低為好),目的是增加page hit,減少page conflict。

close page方式是結構相對簡單的memory controller主要採用。所以連續地址讀寫和隨機地址讀寫的速度,根據memory controller採用的page策略有關,當然大部分是連續地址讀寫速度更快帶寬更高。

另外,從讀命令到寫命令所用切換時間比從寫到讀少,這是因為數據操作其實主要在buffer中進行,如果前一個是讀,讀命令不會影響數據,buffer中數據始終和open的行中數據保持一致,所以pre-charge的時候不需要把buffer中數據寫回行中。而寫命令會改變數據,需要一個寫回的過程。所以還盡量要減少寫到讀的切換,在保證正確讀寫順序的基礎上。


先說結論吧:DRAM的隨機讀寫速度必然慢於連續讀寫。

主要原因是CPU存在著多層次的cache,隨機讀寫會造成大量的cache miss,必然引發速度下降。除非是完全沒有cache的CPU,比如Intel第一代的8086 CPU。

因為不存在cache,所以隨機讀寫速度基本上跟連續讀寫是一樣的,但8086的隨機跳轉性能會差一些,因為8086上還是有幾個位元組的指令預取緩存的。

回到題主的問題,段頁式轉化是必然要產生性能損失的,極端的例子是虛擬化,虛擬化是兩次翻譯,先從虛擬機的虛地址轉換成虛擬機的物理地址,再轉換成實際物理地址,所以虛擬機的內存訪問性能要慢於非虛擬機,但這個浪費並不是「很大」,Intel號稱虛擬機的內存訪問性能比非虛擬化模式慢10%~30%左右,這是過去的數據,不知道現在什麼樣了,所以算不上「浪費很大」。

實際CPU在翻譯段頁地址的時候,頁面內的地址翻譯是有緩存的,比如對於指令來說,只要不踩到頁邊界,是不會觸發新的地址翻譯(這裡特別說明一下:操作系統從實模式切換到保護模式的時候,也用了這種技巧:不跨頁,不觸發地址翻譯)。而跨頁的話,也並非到RAM里拿頁表,那樣開銷太大了,有TLB的存在可以提高地址翻譯速度。

BIOS層面上的物理地址到實際物理設備的地址翻譯是在內存控制器里做的,這方面可以認為是沒有性能損耗的,因為翻譯的過程是可以認為是靜態的,就算是有開銷,也遠遠低於虛地址的翻譯——這個是動態的,因為頁表是可調整的。

不管地址翻譯的開銷有多大,也比不上cache miss,這個會嚴重影響性能。

有一些特殊的應用場合,會為了保證性能或者實時性,會關掉頁表,或者做大頁一一映射,這就是為了盡量讓地址翻譯的影響降到最低。

-------------------------------

再說SSD的問題,SSD是不需要尋道,但SSD也是有cache的,SSD內部有一張表,保存著邏輯扇區到物理扇區的映射,為了保證性能,這個映射表運行時是被SSD放到主控的cache里的,但基於成本的考慮不會是全cache的,那麼這裡就會有cache miss的可能,cache miss的開銷可能是微秒甚至毫秒級,這樣延遲就很大了。

隨機寫就更複雜一點,除了SSD本身的cache miss之外,SSD寫操作的最小單元要大於讀,SSD讀的最小單位一般是一個扇區(512B/4K),擦除的最小單位是一個block,可能是128KB甚至更大,擦除一個block的開銷是毫秒級的延遲,如果連續寫128KB,可能是只需要擦除一個block,但如果是隨機寫,那可能是擦除非常多的block,其開銷是完全不一樣的。

所以即使SSD不需要尋道,其隨機讀寫的性能也慢於連續讀寫。


真正的隨機存儲貴啊,

cpu的論個算的寄存器就是,論kb算的l1緩存也算是吧(雖然也是以行為單位,但粒度比內存里要小多了),要實現同容量所需晶體管比內存那串列的結構得多出個量級,而且非常難放大規模(就像道路密度大就住宅少會放大交通需求一樣,超大城市不分區你規劃99%道路一樣會堵死),

ssd存儲粒度比內存更大,同容量比內存所需晶體管少的多還不需要那麼高頻.,所以速度會慢更多.


連續和隨機讀寫速度不一樣,同樣是隨機讀寫比連續讀寫慢不少。

虛擬內存的策略是時間換空間,本身的意義就是犧牲性能換空間,可以讓程序裝進去運行而不是不夠用。

地址轉換是為了方便地址管理吧,不然大家都用物理地址管理起來亂糟糟的。。

你這個追求絕對性能的思路很激進啊


ram既然叫隨機存儲器,顧名思義讀取時間與信息的位置無關。

ssd使用的nand flash以頁為單位讀取數據,每次至少讀寫一個page。這樣連續讀寫速度肯定高於需要每次進行定址的隨機讀寫速度。

內存分頁的確會降低隨機速度。但是如果ram不分頁,採用連續存儲的方式。反覆進出,內存中產生大量的碎片,就無法繼續使用了。


推薦閱讀:
相关文章