当我为我的算法编写基准测试时,我对一个问题感到困惑!
我的测试代码详细信息已推送到 github,我将其复制到此处并添加一些注释。
https://github.com/hidstarshine/Algorithm/blob/master/leet/problem24_test.go
var TDBenchmarkSwapPairs1 *leet.ListNode
// This function may be not good, it should be init()?
func FTDBenchmarkSwapPairs1() {
TDBenchmarkSwapPairs1 = &leet.ListNode{
Val: 0,
Next: nil,
}
changeNode := TDBenchmarkSwapPairs1
for i := 1; i < 100; i++ {
changeNode.Next = &leet.ListNode{
Val: i,
Next: nil,
}
changeNode = changeNode.Next
}
}
func BenchmarkSwapPairs1(b *testing.B) {
FTDBenchmarkSwapPairs1() // problem is here
for i := 0; i < b.N; i++ {
leet.SwapPairs1(TDBenchmarkSwapPairs1)
}
}
Run Code Online (Sandbox Code Playgroud)
在问题行中,我调用FTDBenchmarkSwapPairs1(FTD表示填充测试数据)来初始化数据。
然后令人惊奇的事情发生了,BenchmarkSwapPairs1 似乎在许多 goroutine 中运行。
因此并发带来了数据竞争,并且由于 SwapPairs1 特殊逻辑,调试变得一团糟。
SwapPairs1 将更改 ListNode 中的 Next。
然后我想将 BenchmarkSwapPairs1 移动到 for 块来解决这个问题。
但数据竞争似乎仍未解决,并且由于初始化时间的原因,基准测试没有任何意义。
我在leetcode上判断了算法并被接受了!
问:我怎样才能优雅地解决这个问题?需要一个好主意!
新@Jimb
我添加只是添加一些调试信息然后它会出现恐慌。我还认为一开始就不会出现数据竞争。
当我看到恐慌时我做出了假设!
package leet_test
import (
"fmt"
"testing"
"github.com/hidstarshine/Algorithm/leet"
)
var TDBenchmarkSwapPairs1 *leet.ListNode
func FTDBenchmarkSwapPairs1() {
TDBenchmarkSwapPairs1 = &leet.ListNode{
Val: 0,
Next: nil,
}
changeNode := TDBenchmarkSwapPairs1
for i := 1; i < 100; i++ {
changeNode.Next = &leet.ListNode{
Val: i,
Next: nil,
}
changeNode = changeNode.Next
}
AnotherChangeNode := TDBenchmarkSwapPairs1
for AnotherChangeNode != nil {
fmt.Println(AnotherChangeNode)
AnotherChangeNode = AnotherChangeNode.Next
}
}
func BenchmarkSwapPairs1(b *testing.B) {
FTDBenchmarkSwapPairs1()
for i := 0; i < b.N; i++ {
fmt.Println(TDBenchmarkSwapPairs1.Next)
fmt.Println(TDBenchmarkSwapPairs1.Next.Next)
fmt.Println(TDBenchmarkSwapPairs1.Next.Next.Next)
fmt.Println(TDBenchmarkSwapPairs1.Next.Next.Next.Next)
leet.SwapPairs1(TDBenchmarkSwapPairs1)
}
}
Run Code Online (Sandbox Code Playgroud)
恐慌信息(重要)
more...
&{98 0xc000044ac0}
&{99 <nil>}
&{1 0xc000044270}
&{2 0xc0000444a0}
&{3 0xc0000444c0}
&{4 0xc0000444d0}
Some system info
&{15 0xc000044ae0}
&{2 0xc000044bd0}
&{17 0xc000044b00}
&{4 0xc000044bf0}
&{17 0xc000044ae0}
Unorderd message
<nil>
&{4 0xc000044ae0}
&{2 <nil>}
<nil>
panic: runtime error: invalid memory address or nil pointer dereference // why
[signal 0xc0000005 code=0x0 addr=0x8 pc=0xbefb20]
Run Code Online (Sandbox Code Playgroud)
如果您有多个基准测试函数,您可能不希望它们干扰彼此的数据,因此请使用局部变量而不是(共享)包级变量。
您可以使用*B.ResetTimer从总体基准运行时间中删除设置时间。
func BenchmarkSwapPairs1(b *testing.B) {
root := &leet.ListNode{
Val: 0,
Next: nil,
}
changeNode := root
for i := 1; i < 10000; i++ {
changeNode.Next = &leet.ListNode{
Val: i,
Next: nil,
}
changeNode = changeNode.Next
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
root = leet.SwapPairs1(root)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2563 次 |
| 最近记录: |