所以我决定在 golang
中为我的函数编写测试。该函数本身如下所示:
func Insert(slice []int, element int, index int) []int {
n := len(slice)
slice = slice[:(n + 1)]
for i := index; i < n; i++ {
slice[i+1] = slice[i]
}
slice[index] = element
return slice
}
因此它需要一个 slice ,将其长度扩展 1 并在给定索引处插入一个元素。现在,在调用它之前,我必须做两件事:
size := somevalue
array := make([]int, size, size+1)
然后是f.e array = Insert(array, 1, len(array)/2
。现在我写了insert_test.go
:
package sdizo
import "testing"
func benchmarkInsert(size int, b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
array := make([]int, size, size+1)
array = Insert(array, 1, len(array)/2)
}
}
func BenchmarkInsert10k(b *testing.B) { benchmarkInsert(10000, b) }
func BenchmarkInsert20k(b *testing.B) { benchmarkInsert(20000, b) }
func BenchmarkInsert30k(b *testing.B) { benchmarkInsert(30000, b) }
func BenchmarkInsert40k(b *testing.B) { benchmarkInsert(40000, b) }
func BenchmarkInsert50k(b *testing.B) { benchmarkInsert(50000, b) }
问题是,测试循环中有 2 个操作。我无法移动 make()
在循环上方,因为每次尝试向其中插入内容时都必须创建一个新数组(不想弄乱容量)。它有效,它给了我输出,但我很好奇这是否 make()
不会扰乱时间测量,我想问你是否可以以某种方式仅测量 Insert()
的时间
P.S 有没有一种方便的方法将基准测试的结果写入文件?
最佳答案
例如(从 Go 1.7 开始),使用您的 Insert
算法,
package sdizo
import (
"strconv"
"testing"
)
func Insert(slice []int, element int, index int) []int {
n := len(slice)
slice = slice[:(n + 1)]
for i := index; i < n; i++ {
slice[i+1] = slice[i]
}
slice[index] = element
return slice
}
func BenchmarkInsert(b *testing.B) {
for size := 10000; size <= 50000; size += 10000 {
b.Run(strconv.Itoa(size/1000)+"k",
func(b *testing.B) {
a := make([]int, size, size+1)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
a = a[:size]
a = Insert(a, 1, len(a)/2)
}
b.StopTimer()
},
)
}
}
输出:
$ go test -bench=.
goos: linux
goarch: amd64
pkg: sdizo
BenchmarkInsert/10k-4 50000 32502 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/20k-4 20000 64364 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/30k-4 20000 97310 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/40k-4 10000 129196 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/50k-4 10000 161427 ns/op 0 B/op 0 allocs/op
PASS
ok so/sdizo 9.778s
$
现在我们可以对您的Insert
算法进行基准测试,我们可以利用这些知识来改进算法。例如,
package sdizo
import (
"strconv"
"testing"
)
func Insert(slice []int, element int, index int) []int {
slice = slice[:len(slice)+1]
copy(slice[index+1:], slice[index:])
slice[index] = element
return slice
}
func BenchmarkInsert(b *testing.B) {
for size := 10000; size <= 50000; size += 10000 {
b.Run(strconv.Itoa(size/1000)+"k",
func(b *testing.B) {
a := make([]int, size, size+1)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
a = a[:size]
a = Insert(a, 1, len(a)/2)
}
b.StopTimer()
},
)
}
}
输出:
$ go test -bench=.
goos: linux
goarch: amd64
pkg: sdizo
BenchmarkInsert/10k-4 200000 7664 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/20k-4 100000 15208 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/30k-4 100000 22959 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/40k-4 50000 35181 ns/op 0 B/op 0 allocs/op
BenchmarkInsert/50k-4 50000 39658 ns/op 0 B/op 0 allocs/op
PASS
ok so/sdizo 10.331s
$
关于在 golang 中测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43023702/