測試go多協程併發寫入記憶體和磁碟對效能的影響
阿新 • • 發佈:2018-12-17
最近希望能把一些過程,由傳統的順序執行改變成併發執行,看這樣的優化是否能帶來效能的提高。於是寫了幾個test來測試帶來的影響。 測試的環境為mac pro,2.3 GHz Intel Core i5(雙核),16GB記憶體。
(1)先測試併發寫入記憶體是否能夠得到效能的提高
測試程式碼如下:
func TestMemoryDB_SequenceExecute(t *testing.T) { db := New() t1 := time.Now() //如果是同一個key只會覆蓋,無法測試出效能,因此需要是不同的key來測,寫入同一個key需要的時間約等於不同key的一半時間 //1億次 for i := 0; i < 100000000; i++ { err := db.Put([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2"+string(i)), []byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } t2 := time.Now() fmt.Println("spend time:", t2.Sub(t1)) //2.337S } func TestMemoryDB_ConcurrentExecute(t *testing.T) { db := New() wg := sync.WaitGroup{} wg.Add(2) t1 := time.Now() exec1 := func() { for i := 0; i < 50000000; i++ { err := db.Put([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2"+string(i)), []byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } wg.Done() } exec2 := func() { for i := 2500000; i < 5000000; i++ { err := db.Put([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2"+string(i)), []byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } wg.Done() } go exec1() go exec2() wg.Wait() t2 := time.Now() fmt.Println("spend time:", t2.Sub(t1)) }
經測試順序寫入上述字串1億次,耗時40秒左右,開一個協程和開兩個協程的耗時也是在40秒左右,如果開兩個協程以上執行,耗時反而增多。因為越多協程,需要的排程和切換的時間會增多。
(2)再測試併發寫入磁碟檔案是否能夠得到效能的提高
因為磁碟的效能比記憶體的效能要低一個數量級別以上,因為只寫入100萬次剛才的字串。
測試程式碼如下:
func TestFile_SequenceWrite(t *testing.T) { f, _ := os.Create("./output.txt") defer f.Close() t1 := time.Now() for i := 0; i < 10000000; i++ { _, err := f.Write([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } t2 := time.Now() fmt.Println("spend time:", t2.Sub(t1)) } func TestFile_ConcurrentWrite(t *testing.T) { f1, _ := os.Create("./output1.txt") f2, _ := os.Create("./output2.txt") wg := sync.WaitGroup{} wg.Add(2) t1 := time.Now() go func() { for i := 0; i < 5000000; i++ { _, err := f1.Write([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } wg.Done() }() go func() { for i := 5000000; i < 10000000; i++ { _, err := f2.Write([]byte("0x6766c3279a7b32e52e89b24d203dd311aaf3019f9dd182f0128d8f12ab4490c2")) if err != nil { t.Fatalf("put failed: %v", err) } } wg.Done() }() wg.Wait() t2 := time.Now() fmt.Println("spend time:", t2.Sub(t1)) }
經測試,寫入一個66位元組的字串100萬次 到一個檔案裡,如果順序執行,需要耗時65-70秒左右(測了三次:66,66,69秒)。如果開兩個協程併發寫入一個檔案,耗時在75-80秒左右。但如果開兩個協程併發寫入兩個不同的檔案,耗時在40-50秒左右(測了6次:52,44,41,40,45,42秒)。如果開兩個協程以上併發寫入多個檔案,不會再有效能的提高。