Testing 在golang中测试函数
所以我决定在Testing 在golang中测试函数,testing,go,Testing,Go,所以我决定在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 sl
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
}
type Slice struct {
contents []interface{}
length int
capacity int
}
然后f.earray=Insert(array,1,len(array)/2
。现在我写了Insert\u 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) }
package-sdizo
导入“测试”
func benchmarkInsert(size int,b*testing.b){
b、 重置计时器()
对于n:=0;n
问题是,在测试循环中有两个操作。我不能将make()
移动到循环上方,因为每次它尝试插入一些东西时都必须创建一个新数组(不想影响容量)。它工作正常,它会给我输出,但我很好奇这make()
不会影响时间测量,我想问您,我是否可以仅为Insert()测量时间
有没有一种方便的方法将基准测试的结果记录到一个文件中?编辑:你寻找的真实答案。(最后)
当您进行基准测试时,实际上要对您想要进行基准测试的内容进行基准测试。您的用例不会是make,然后每次插入,所以只需进行一次,然后在循环中测试插入。关键是只测试阻塞点
这里要做的就是测试Insert
。您只需每次调整数组的大小即可,其成本基本上是零(至少与make
或Insert
相比)
使用array=array[0:size]
执行调整其大小的操作类似于设置结构的length=size
。请参阅
至于将结果写入文件,这取决于您的操作系统。在任何Unix系统上,只需在最后运行带有>file.txt
的基准命令,结果就会通过管道传输到file.txt
。对于Windows不确定
编辑:添加更多测试将显示此项线性扩展
BenchmarkInsert10k-8 200000 7889 ns/op
BenchmarkInsert20k-8 100000 16131 ns/op
BenchmarkInsert30k-8 100000 24184 ns/op
BenchmarkInsert40k-8 50000 31767 ns/op
BenchmarkInsert50k-8 50000 39721 ns/op
BenchmarkInsert100k-8 20000 79711 ns/op
BenchmarkInsert200k-8 10000 159411 ns/op
BenchmarkInsert300k-8 5000 237188 ns/op
BenchmarkInsert400k-8 5000 316270 ns/op
BenchmarkInsert500k-8 3000 399146 ns/op
BenchmarkInsert1000k-8 2000 793845 ns/op
使用此代码:例如(从Go 1.7开始),使用插入算法
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()
},
)
}
}
现在我们可以对您的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()
},
)
}
}
以这种方式实现函数有点古怪:现在你依赖调用方提供足够大的切片,否则就会惊慌失措。我知道,但我如何才能使它不同,使它工作?更快,但这不是不正确吗?我认为你的追加
应该在元素
分配到pre[index]之前进行
。你是对的,它仍然引用片中相同的元素。我现在修复了它。必须分配一个新的元素,这会减慢速度。但是,这个技巧的速度大约是我的两倍……不幸的是,它没有我原来想的那么酷。@PaulHankin好的,现在它超级快速和正确。如果我不能使用append呢(必须自己做每一个算法)。顺便说一句,我检查了你的版本,速度更快,但图表看起来是这样的(大概是一条直线)。我的意思是,你得到的数据足够好了,我猜(倍数越大x2,x1.5,x1.33,x1.25),但在我的情况下不是。你不知怎么改变了测试吗?@Edit,好吧,我在Windows上测试了它,它运行得非常好,我想我将不得不在VM上告别Linux:(我的一个编辑有一个更快的算法:P.哈哈,对不起,只是开玩笑。OP无论如何都不会进行优化,所以我从我的答案中删除了杂乱无章的内容。
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
$
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
$