第二節:內存層次結構
當有人們提到“內存”這個詞的時候,往往都與主板上的專門提供數據存儲能力的芯片聯系起來。通常將這類提供存儲能力的芯片稱之為隨機存儲器(RAM),主內存(main memory),和主存儲器(primary storage).回首計算機的鐵器時代,大型機大行其道的時候,稱之為核心部件(core)。這些芯片提供的存儲只是臨時的,也就是說,存儲在這些芯片里的數據只要當電源被關閉以后也隨之消失。
有這么幾類RAM
動態 RAM(DRAM)一秒鐘內會進行數千次的充電動作。同步 DRAM (SDRAM) 隨著處理器高速的時鐘運行速度下保持同步刷新。靜態 RAM(SRAM)不需要像DRAM那樣頻繁的刷新,這使得它的速度大大加快。不幸地是,SRAM的價格也比DRAM昂貴得多,只得以被少量的使用。 SRAM適合用于處理器的高速緩存,DRAM則適用于大規模的主存儲器。最后還有一種視頻RAM(VRAM),它是一種有視頻硬件使用的一類內存。在下一章中,會有一個例子用語演示如何通過控制VRAM來向屏幕輸出信息。
最近隨著某些硬件廠商對技術的不斷進步和特別的性能優化實現又衍生出很多新的縮寫出來,下面有幾個:
DDR SDRAM是雙倍數據傳輸速率的同步隨機存儲器。使用DDR SDRAM 數據可以在一個系統時間周期的上升沿和下降沿同時讀取數據,基本上兩倍于常規的可用帶寬。RDRAM是Rambus DRAM的簡稱,由Rambus公司出售的高性能版本的DRAM,它可以達到800MHz的傳輸速率。增強型的同步DRAM(ESDRAM),由 Enhanced Memory Systems,Inc 公司生產,作為取代SRAM的一種更廉價的SDRAM。
1(bit)比特是一個二進制數,(例如一個1或者一個0)。RAM中由比特這樣的基本單元結構構成,依據RAM的類型,以某種晶體管和電容器的布局方式組成。每一個單元是一個可以設置為‘開’ 和‘關’的數字開關(例如:1或者0)。這些單元每八個分為一組成為字節(bytes)。字節是用來計量存儲器所提供的內存總量的的基本單位。在過去,硬件廠商曾經使用不同大小的byte單位。有些使用6比特作為一個字節,還有使用16字節作為一個字節。而現在所有人都遵守了相同的8比特一為個字節的標準。
以下是以byte為單位的內存單位容量說明。
1 byte = 8bits
1 word = 2bytes
1 double word = 4bytes
1 quad word = 8bytes
1 octal word = 8bytes
1 paragraph = 16bytes
1 kilobyte(KB) = 1,024bytes
1 megabyte(MB) = 1,024KB = 1,048,576bytes
1 gigabyte(GB) = 1,024MB = 1,073,741,824bytes
1 terabyte(TB) = 1,024GB = 1,099,511,627,776bytes
1 petabyte(PB) = 1,024TB = 1,125,899,906,842,624bytes
注解:在80年代,擁有一個上M的DRAM內存已經很了不起了。孩子們不斷的游說父母再升級16KB的內存,讓他們在Atari400可以玩上更復雜一些的游戲。在那個時候只有1M內存并不是什么大問題,因為軟件工程師們都傾向使用匯編代碼構建更加精巧的程序。實際上,經常有人引用比爾蓋茨于1981年的一句話:"640K的內存對于每個人都綽綽有余了"
而今,大多數用于開發的計算機至少擁有128M的DRAM,在2002年擁有256M被視為是標準配置。此后的十年內。上G的內存將作為標準配置出現。(如果我們仍使用DRAM)。希望以后不要有人引用我的這段話。
RAM并不是唯一存儲數據的地方,這里引出了我們內存層次結構的議題。不同的數據存儲位置,根據與處理器的遠近關系排列。排列后產生了如下層次結構:
1.Registers 寄存器
2.Cache 高速緩存區
3.RAM 主內存
4.Disk storage 硬盤
這些存儲器之間最大的區別在于存儲時滯或者說延遲。訪問靠近處理器的存儲設備所用的時間比相對稍遠處理器的存儲器少。處理器訪問硬盤上數據的時間遠遠的大于處理器訪問它內部的高速緩沖區數據的響應速度。比如,DRAM往往使用納秒來衡量時滯,而硬盤的時滯,卻是用毫秒來衡量!(如下表1.1)
圖 1-1
寄存器是位于處理器內部的小型存儲器。寄存器是處理器鐘愛的工作區。處理器的大部分日常工作是對寄存器中的數據進行處理。將數據在寄存器之間移動,是最為實用的數據移動方式。工程師們在設計的編譯器時跨越種種難題,力求將所有變量和常量都保存在寄存器中。應用程序狀態保存在處理器內部所擁有的大量寄存器中從而降低了存儲時滯。因此MIPS64處理器設計了32個64位的通用寄存器。安騰——INtel的下一代64位處理器,更加不可匹敵,它有用竟然數百個寄存器。
Intel Pentium處理器擁有多種寄存器(如圖 1-2)其中:6中16位的段寄存器(CS,DS,ES,FS,GS,SS)。8位,32位通用寄存器(EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP )還有一個32位的錯誤標志寄存器(EFLAGS)用以標識錯誤狀態,以及一個32位的指令指針寄存器(EIP)。

圖 1-2
高級內存管理的功能得到由四種系統寄存器(GDTR,LDTR,IDTR,TR)和五種模式控制寄存器(CR0,CR1,CR2,CR3,CR4)協助。這些寄存器的使用方法會在后面介紹。
注釋: 注意很有意思的是由于歷史的原因Pentium處理器的寄存器數量受到了限制。由于向后的兼容性的設計需求,使得Pentium處理器所擁有的寄存器數量比當年的8086沒有太多增加。
高速緩沖區提供訪問速度大于DRAM的臨時存儲器。通過將程序部分集中放置在高速緩沖區中的進行運算的方式,處理器可以避免重復訪問DRAM所帶來的性能開銷,這個效果十分顯著。有不同類型的高速緩沖區。L1緩沖區是位于存儲器內部的存儲器。L2是典型的SRAM類型存儲器,于處理器外部。(例如,Intel Pentium4搭載了這樣256或者512KB的高速緩存器)
注釋: 如果你正在嘗試針對高速緩沖區優化程序代碼,你應該避免不必要的函數調用。調用一個遠程函數需要處理器執行高速緩沖區以外的代碼。這將會導致重新裝載高速緩沖區里的內容。這也便是為什么某些C編譯器提供內聯函數功能選項的原因。從另一個方面來說,使用內聯函數比不使用內聯函數的程序體積更大(占用更多的存儲器空間)時間和空間的互換的取舍平衡的問題一直貫穿整個計算科學領域。
硬盤是數據存儲的最后一個位置。通常,硬盤常常用于創建虛擬內存。虛擬內存使用硬盤空間來模擬主內存。換言之,將一部分存儲在DRAM上的數據寫入硬盤,處理器便可以訪問的內存總量大于實際物理內存。例如,如果你有10MB的DRAM內存并且使用了2MB的硬盤空間作為虛擬內存,處理器便可以訪問12MB的虛擬內存。
注釋:我將在本書中反復重申的一點是硬盤I/O的嚴重性能損耗。正如我之前所提到的,硬盤是使用毫秒為單位來橫定響應能力的。處于處理器來說這個時間太過漫長。這個情形就類似遠在北達科他州做pizza的小店,如果運氣好的話,你冰箱里有一個冷凍pizza,加熱只需要30分鐘。否則你不得不給那個pizza小店叫份pizza外賣(就好象訪問硬盤上的數據)然后花上幾個小時等待外賣小子跨越150英里的距離送到你的房間。
使用虛擬內存就好象跟魔鬼打交道,當然你會獲得很多擴展內存,但是你會在性能上付出昂貴的代價。硬盤I/O涉另一整套的操作行為,其中還有一些物理機械性的。Windows系統的內存分頁,粗略的估計會因此占用10%的執行時間。管理虛擬內存還需要生成大量的內存信息記錄。我會在后面詳細的談論有關虛擬內存信息記錄的內容。
題外話
我曾經在一家ERP的公司工作過,其中一位副主管常常對過度濫用硬盤I/O的工程師處以罰金。在代碼復審時候,他會用grep命令搜索源代碼里面的所有 fopen()和fread()標準庫函數。我們接受了這樣基本課程:你應該盡可能的將一切緩存到內存中只有在別無選擇的情況下才將數據保存到硬盤中(這個操作甚至需要得到他的許可)。歸功于該副主管,公司的三層中間件產品成為產業中性能最高的。
硬盤總是比RAM便宜,在60年代買一塊8KB的RAM花費不菲,用硬盤虛擬內存或許很有意義。今天,硬盤和DRAM的價格差距并不是像以前那樣那么明顯了。買一臺512MB內存的計算機并不是大不了的事情。虛擬內存可能會完全成為歷史或者成為某些緊急情況下的數據安全方案。