如何讓磁碟擁有記憶體一樣的讀寫速度
阿新 • • 發佈:2021-08-14
磁碟是塊儲存裝置,讀寫連續的一整塊磁碟資料其實還是很快的,平時我們感覺磁碟比記憶體慢是因為沒有順序地讀磁碟,而是在隨機讀,大部分時間都浪費在尋道和旋轉上面。
做個試驗,對比一下順序讀磁碟和讀寫記憶體的速度,看看到底差多少。
試驗方法:建立一個長度為10M的位元組陣列,執行3種操作--順序地訪問該數組裡的元素,隨機地訪問該數組裡的元素,把該數組裡的元素順序地寫入磁碟。
試驗結果:
結論:
1. 順序讀寫記憶體比隨機讀寫記憶體快幾十倍
2.順序讀寫磁碟比隨機讀寫記憶體快幾倍
CPU讀寫磁碟的最小單位是塊,一塊通常是4K,連續整塊整塊的讀寫會非常快。搜尋引擎要儲存海量的文件,它充分利用了磁碟的這一特性,提高文件讀取的速度。對搜尋引擎感興趣的同學可以掃碼進入我的課程-- 《Go語言實現工業級搜尋引擎》。
最後附上測試程式碼:
package serialize import ( "fmt" io "io" "math/rand" "os" "testing" "time" ) const SIZE = int(1e7) //不能再大了,否則會報錯runtime: goroutine stack exceeds 1000000000-byte limit var ( arr [SIZE]byte indexes [SIZE]int ) func init() { for i := 0; i < SIZE; i++ { indexes[i] = i } rand.Seed(time.Now().UnixNano()) rand.Shuffle(SIZE, func(i, j int) { indexes[i], indexes[j] = indexes[j], indexes[i] }) } //順序讀記憶體 func TestReadRAMOrderly(t *testing.T) { begin := time.Now() for _, ele := range arr { _ = ele } fmt.Printf("read RAM unorderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadRAMOrderly //順序寫記憶體 func TestWriteRAMOrderly(t *testing.T) { begin := time.Now() for i := 0; i < SIZE; i++ { arr[i] = 1 } fmt.Printf("write RAM unorderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteRAMOrderly //隨機讀記憶體 func TestReadRAMUnorderly(t *testing.T) { begin := time.Now() for _, i := range indexes { _ = arr[i] } fmt.Printf("read RAM unorderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadRAMUnorderly //隨機寫記憶體 func TestWriteRAMUnorderly(t *testing.T) { begin := time.Now() for _, i := range indexes { arr[i] = 1 } fmt.Printf("write RAM unorderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteRAMUnorderly //順序寫磁碟 func TestWriteDiskOrderly(t *testing.T) { fout, err := os.OpenFile("arr.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm) if err != nil { panic(err) } begin := time.Now() fout.Write(arr[:]) //通過切片[:]把陣列轉slice fout.Close() fmt.Printf("write disk orderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteDiskOrderly //順序讀磁碟 func TestReadDiskOrderly(t *testing.T) { fin, err := os.OpenFile("arr.txt", os.O_RDONLY, os.ModePerm) if err != nil { panic(err) } buf := make([]byte, 1024) begin := time.Now() for { _, err := fin.Read(buf) if err == io.EOF { break } } fin.Close() fmt.Printf("read disk orderly %d ms\n", time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadDiskOrderly //為了避免快取的影響,6個Test函式分6次執行
我的Go語言實戰課 Go語言實現工業級搜尋引擎