1. 程式人生 > >測試go多協程併發寫入記憶體和磁碟對效能的影響

測試go多協程併發寫入記憶體和磁碟對效能的影響

最近希望能把一些過程,由傳統的順序執行改變成併發執行,看這樣的優化是否能帶來效能的提高。於是寫了幾個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秒)。如果開兩個協程以上併發寫入多個檔案,不會再有效能的提高。