drn1008 2017-03-26 00:47
浏览 27
已采纳

在Golang中测试功能

So I've decided to write test for my function in golang. The function itself looks like this:

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
} 

So it takes a slice, extends its length by 1 and inserts an element at given index. Now before I call it I have to do 2 things:

size := somevalue
array := make([]int, size, size+1)

and then f.e array = Insert(array, 1, len(array)/2. Now I wrote 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) }

The thing is, there are 2 operations in testing loop. I cannot move the make() above the loop, cuz it has to make a new array everytime it tries to insert something to it (don't want to mess with capacity). It works, it gives me output, but I am curious if this make() doesn't mess up with time measurement, and I would like to ask you if I can somehow measure the time only for Insert()

P.S Is there a convenient way to write down the results of benchmark test to a file?

  • 写回答

2条回答 默认 最新

  • dpd46554 2017-03-26 13:24
    关注

    For example (from Go 1.7 forward), using your Insert algorithm,

    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()
                },
            )
        }
    }
    

    Output:

    $ 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
    $ 
    

    Now that we can benchmark your Insert algorithm, we can use that knowledge to improve the algorithm. For example,

    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()
                },
            )
        }
    }
    

    Output:

    $ 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
    $
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求MCSCANX 帮助
  • ¥15 机器学习训练相关模型
  • ¥15 Todesk 远程写代码 anaconda jupyter python3
  • ¥15 我的R语言提示去除连锁不平衡时clump_data报错,图片以下所示,卡了好几天了,苦恼不知道如何解决,有人帮我看看怎么解决吗?
  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开