天天看點

測試Go語言的interface的效率

interface是Go語言中的一大特點,甚至說是靈魂也不為過。

interface應該會在Go程式中大量出現和使用,因為有必要了解和測試下它的效率。

測試思路:

使用vector包,測試原生的IntVector和用interface包裝後的vector的效率。

Go1中去掉了vector包,不過當時我把vector的代碼保留了一份,

在代碼庫裡應該也能找到。我找到了一個版本的:

https://code.google.com/p/go/source/browse?name=weekly.2011-08-17#hg%2Fsrc%2Fpkg%2Fcontainer%2Fvector

可能和我測試用的代碼有差别,沒仔細對比過,不過應該差不多。

Go語言中interface的實作:

http://research.swtch.com/interfaces

據作者說一次函數調用要花5條CPU指令(C++的虛函數是3條)。

下面是測試代碼:

package main

import (
	"fmt"
	"time"
	. "vector"
//	"vector/vector"
)

const size = 1000000

func testIntVectorPush() {
	v := make(IntVector, size)
	t0 := time.Now()
	for i := 1; i < size; i++ {
		v.Push(i)
	}
	t1 := time.Now()
	fmt.Printf("The testIntVectorPush call took %v to run.\n", t1.Sub(t0))
	v = nil
}

func testIntVectorAt() {
	v := make(IntVector, size)
	t0 := time.Now()
	for j := 0; j < 1000; j++ {
		for i := 1; i < size; i++ {
			v.At(i)
		}
	}
	t1 := time.Now()
	fmt.Printf("The testIntVectorAt call took %v to run.\n", t1.Sub(t0))
	v = nil
}

func testVectorPush() {
	v := make(Vector, size)
	t0 := time.Now()
	for i := 1; i < size; i++ {
		v.Push(i)
	}
	t1 := time.Now()
	fmt.Printf("The testVectorPush call took %v to run.\n", t1.Sub(t0))
	v = nil
}

func testVectorAt() {
	v := make(Vector, size)
	t0 := time.Now()
	for j := 0; j < 1000; j++ {
		for i := 1; i < size; i++ {
			v.At(i)
		}
	}

	t1 := time.Now()
	fmt.Printf("The testVectorAt call took %v to run.\n", t1.Sub(t0))
	v = nil
}

func main() {
	fmt.Println("abc")
	i := 0
	for ; i < size; i++ {
		i += i
	}
	fmt.Println(i)

	testIntVectorPush()
	testIntVectorPush()
	testVectorPush()
	testVectorPush()

	testIntVectorAt()
	testIntVectorAt()
	testVectorAt()
	testVectorAt()

}
           

測試結果:

The testIntVectorPush call took 19.0011ms to run.

The testVectorPush call took 64.0037ms to run.

The testVectorPush call took 51.0029ms to run.

The testIntVectorAt call took 1.2920739s to run.

The testIntVectorAt call took 1.2990743s to run.

The testVectorAt call took 2.4831421s to run.

The testVectorAt call took 2.5131438s to run.

明顯地原生的IntVector比用interface包裝過的Vector要快2到3倍。

總結:

Go語言中的interface很靈活,但是也付出了一定的性能代價。

如果是性能關鍵的代碼,可以考慮放棄interface,自己寫原生的代碼。

話說回來,沒有泛型機制,真的比較蛋疼,相當期待Go能支援泛型。

關于Go中的泛型,參見:

泛型程式設計的困境

繼續閱讀