1. 程式人生 > 其它 >如何讓磁碟擁有記憶體一樣的讀寫速度

如何讓磁碟擁有記憶體一樣的讀寫速度

磁碟是塊儲存裝置,讀寫連續的一整塊磁碟資料其實還是很快的,平時我們感覺磁碟比記憶體慢是因為沒有順序地讀磁碟,而是在隨機讀,大部分時間都浪費在尋道和旋轉上面。

做個試驗,對比一下順序讀磁碟和讀寫記憶體的速度,看看到底差多少。

試驗方法:建立一個長度為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語言實現工業級搜尋引擎