你知道5分鐘法則和10位元組法則么?
如果一條數據每5分鐘被訪問一次,那麼它應該常駐在記憶體中。類似的,如果想存儲只有0和1兩個值的標誌位,相比於將8個標誌位打包為1個位元組,將1個標誌位單獨存儲為1個位元組是更節約的選擇。
本文參考 Jim Gary(圖靈獎得主)於1987年發表的論文:The 5 minute rule for trading memory for disc accesses and the 10 byte rule for trading memory for CPU time | ACM SIGMOD Record
5分鐘法則
如果數據在磁碟上,需要載入到記憶體進行讀寫,這是需要錢和時間的。在某些特殊情況下,由於磁碟讀寫耗時長因此數據常駐在記憶體上,但數據常駐在記憶體上是不經濟的行為,因此什麼時候數據需要常駐記憶體是一個值得思考的問題。一個好的建議是:
5分鐘法則:每5分鐘訪問一次的數據應當記錄在記憶體中。
注意5分鐘並不是一成不變的,20年前可能是5秒鐘法則,20年後有可能是5小時法則,確切的數據依賴於硬體的價格比率,這裡使用1986年的價格數據進行論證,標準如下:
- 磁碟:支援每秒15次的隨機訪問,價格為15k,因此每秒訪問一次該磁碟的代價為1k(1k/a/s,a為access),若支援該磁碟額外計算和通道代價為1k/a/s,則該磁碟訪問代價為2k/a/s。
- 記憶體:大小為1MB的記憶體,價格為5k,因此該記憶體的存儲代價為5/KB。
如果記錄1KB數據到記憶體中,能夠節省1a/s的磁碟訪問,相當於花費的代價從2K變成了5,即便是節省0.1a/s的磁碟訪問,也是從200的代價變成了5,這是很划算的。如此可以計算,當數據的訪問頻率在0.0025a/s(每秒訪問0.0025次,即400秒訪問1次),是划算到不划算的分界點。
因此,如果一條1KB的數據,訪問頻率大於400秒1次,就應該存儲在記憶體中,反之應該存儲在磁碟中。五分鐘法則便是這個意思(用5分鐘近似400秒,具體幾分鐘不重要,主要是描述這個計算方式)。對於更小的數據,盈虧分界點會更大一些,對於更大的數據,盈虧分界點會更小一些。
如果數據的大小超過了單次磁碟傳輸數據塊的大小,例如100KB數據會分成25個4KB大小的數據傳輸。因此這種情況下100KB的數據按照4KB來計算盈虧分界點,為0.01a/s(100秒訪問1次)。
公式推導
一個更正式的推導為:
- RI:訪問數據的預期間隔,單位second/access。
- M:記錄1位元組數據到記憶體的代價,單位dollor/byte。
- A:每秒一次磁碟訪問的成本,單位dollor/access/second。
- B:數據的大小,單位byte。
- Bmax:最大磁碟傳輸塊大小,單位byte。
假設B < Bmax,記錄數據到記憶體能節省的代價為:
\]
當等式為0,即盈虧分界點,RI的值為:
\]
當 A = 2000,M = 0.005,如下圖所示為 RI = f(B) 的函數影像。帶入 B = 1000, 可以得出 RI = 400s/a, 即 0.0025a/s。
應用分析
通過一個案例說明5分鐘法則的實際應用,客戶想將資料庫中的所有數據記錄到記憶體中,該資料庫有50萬條記錄,每條記錄大約1KB,因此整個資料庫約有500MB大小,通過5分鐘法則來證明採用記憶體磁碟混合存儲是一個更好的設計。
該應用的事務很簡單,幾乎所有的事務都只是訪問單條記錄,需要1秒的響應時間。每個事務佔用40ms的CPU和30ms的磁碟。整個應用的最大負荷為600tps(每秒600個事務)。
全記憶體的設計中,大概需要36個TXP處理器,每個處理器對應16MB的記憶體。以及兩個磁碟存儲整個資料庫、索引和程式。由於所有數據記錄在記憶體中,大部分時間磁碟是空閑的。
根據5分鐘法則,只有訪問間隔小於5分鐘的數據才應該記錄在記憶體中。並且Hoelshken發現,3%的數據佔據了全部訪問次數的80%(和二八定律差不多)。統計表明對於600TPS的最大負荷,在50萬條記錄中,只有30000條記錄會在5分鐘內被訪問2次,並且這6%的數據佔全部訪問次數的96%。
如果將這6%的數據記錄到記憶體中,每秒的磁碟訪問次數會從600降低到24(600*4%)次。存儲數據的兩個磁碟可以輕鬆撐起24tps的負荷。這樣的設計可以節省470MB(500-500*4%)的記憶體和6個處理器。任何應用程式的數據訪問都可以使用這個邏輯計算磁碟和記憶體的最佳大小。
5分鐘法則還適用於虛擬記憶體管理,例如每2分鐘訪問一個虛擬記憶體頁面(一般4KB),那麼該頁面就應該記錄在記憶體中,因此一個好的時鐘頁面置換演算法應該有足夠的記憶體在峰值負載下保證每分鐘能輪轉一次,或者能夠檢測hot頁面(比如一個2分鐘的窗口),並對hot頁面有特殊的處理。
10位元組法則
另一個問題是,什麼情況下使用記憶體資源來節約計算資源(cpu)更划算?或者相反的,犧牲一些計算資源來節省一些記憶體?這個問題在編寫程式碼時表現為通過展開循環來保存一些數據,或用額外的指令從位元組中提取某個比特。
類似於5分鐘法則,假設記憶體成本為5/KB,每秒執行一條指令的成本為0.05,這和10位元組的記憶體成本一致,因此就有了10位元組法則:
10位元組法則:10位元組的記憶體資源的成本和每秒執行1條指令的計算資源的成本相等。
公式推導
一個更正式的推導為:
- I:新的設計可以減少的程式的指令的數量。
- F:指令執行的頻率,單位1/second。
- S:新的設計增加了多少記憶體,單位byte。
I*F指新的設計總共省去的指令數量,如果新的設計增加了執行的指令,那麼I*F的值為負數。根據10位元組法則,總節省成本為:
\]
如果它是一個很大的正數,就說明新的設計節約了很大的成本。
應用分析
例如有如下程式有三個指令,該程式每秒被調用1000次。
1. 載入一個位元組,該位元組存儲了8個flag,對應8個比特
2. 利用位掩碼獲取其中一個flag
3. 判斷這個flag的值
- 如果一個flag使用一個位元組來存儲,那麼這個程式就不需要指令2,整個程式只需要兩個指令,則表示每秒節約了1000次指令的執行。
- 根據10位元組法則,節約1000次指令每秒的計算資源,相當於節省了10000位元組的記憶體資源。
- 如果一個flag使用一個位元組來存儲,意味著需要8倍的記憶體資源,如果總共需要處理100個flag,意味著記憶體需求從12個位元組變成了100個位元組,多了88個位元組(論文是88,所以不要糾結12*8=96的問題了)。
- 犧牲了88位元組的記憶體資源,節約了1000次指令每秒的計算資源,也就是10000位元組的記憶體資源,因此凈節省為10000-88=9912的記憶體資源, 投入回報比約為1:100,是非常划算的改變。
帶入公式為:I = 1,F = 1000,S = 88,1*1000 – 88/10 = 991.2。
總結
這些規則背後的思想是權衡經濟成本評估設計決策的方法,隨著硬體性價比的改變,這些規則也會改變。在未來,5分鐘法則可能變成5小時法則,10位元組法則可能變為100位元組法則。


