來看兩個程式來比較interface跟特定型別的效能
func BenchmarkGeneric(b *testing.B) {
repeat := func(
done <-chan interface{},
values ...interface{},
) <-chan interface{} {
valueStream := make(chan interface{})
go func() {
defer close(valueStream)
for {
for _, v := range values {
select {
case <-done:
return
case valueStream <- v:
}
}
}
}()
return valueStream
}
take := func(
done <-chan interface{},
valueStream <-chan interface{},
num int,
) <-chan interface{} {
takeStream := make(chan interface{})
go func() {
defer close(takeStream)
for i := 0; i < num; i++ {
select {
case <-done:
return
case takeStream <- <-valueStream:
}
}
}()
return takeStream
}
toString := func(
done <-chan interface{},
valueStream <-chan interface{},
) <-chan string {
stringStream := make(chan string)
go func() {
defer close(stringStream)
for v := range valueStream {
select {
case <-done:
return
case stringStream <- v.(string):
}
}
}()
return stringStream
}
done := make(chan interface{})
defer close(done)
b.ResetTimer()
for range toString(done, take(done, repeat(done, "a"), b.N)) {
}
}
func BenchmarkTyped(b *testing.B) {
repeat := func(done <-chan interface{}, values ...string) <-chan string {
valueStream := make(chan string)
go func() {
defer close(valueStream)
for {
for _, v := range values {
select {
case <-done:
return
case valueStream <- v:
}
}
}
}()
return valueStream
}
take := func(
done <-chan interface{},
valueStream <-chan string,
num int,
) <-chan string {
takeStream := make(chan string)
go func() {
defer close(takeStream)
for i := num; i > 0 || i == -1; {
if i != -1 {
i--
}
select {
case <-done:
return
case takeStream <- <-valueStream:
}
}
}()
return takeStream
}
done := make(chan interface{})
defer close(done)
b.ResetTimer()
for range take(done, repeat(done, "a"), b.N) {
}
}
goos: darwin
goarch: arm64
BenchmarkGeneric
BenchmarkGeneric-10 1879737 646.5 ns/op
BenchmarkTyped
BenchmarkTyped-10 3012214 399.4 ns/op
PASS
BenchmarkGeneric 函數:
使用了 interface{} 作為參數和返回值,這意味著它是通用型的,可以用於任何數據類型。
定義了三個函數:repeat, take, 和 toString。其中,toString 函數將通用型 channel 的值轉換為 string 型別。
基准測試的工作流程是:先用 repeat 生成一連串的 "a" 字符串,然後用 take 從這些字符串中取 b.N 個值,最後用 toString 將這些值轉換為 string 並遍歷它們。
BenchmarkTyped 函數:
是專用型的,特定於 string 數據類型。這意味著這個函數在其內部只處理 string 數據類型,不使用 interface{}。
只定義了 repeat 和 take 兩個函數,因為我們已知輸入和輸出都是 string,所以不需要 toString 函數。
基准測試的工作流程是:先用 repeat 生成一連串的 "a" 字符串,然後用 take 從這些字符串中取 b.N 個值並遍歷它們。