我使用回溯编写了一个小型数独求解器。现在我想对此功能的速度进行基准测试。这是我目前的代码:
type Board struct {
Cells [9][9]int
}
func BenchmarkBacktrack(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
// prevent the modification of the orignal board
copy := &Board{
Cells: exampleBoard.Cells,
}
b.StartTimer()
copy.Backtrack()
}
}
由于&Board
是指针,我会在第一次迭代中解决数独,而在下一次迭代中,我会回溯一个已解决的板。因此,我在每次迭代开始时重置电路板。 exampleBoard
填充了样本值。
他们是一种更好的方法来对功能进行基准测试而不会反复停止和重新启动计时器吗?
并且不会花费函数调用影响基准的少量时间吗?
答案 0 :(得分:1)
您可以尝试提供func NewBoard([9][9]int) *Board
方法,该方法只是从示例数据初始化电路板。然后在新主板和Backtrack()
的单独基准上编写NewBoard()
的基准。
减去这两个数字应该可以让你了解Backtrack方法的速度。
type Board struct {
Cells [9][9]int
}
var scratch *Board
func NewBoard(cells [9][9]int) *Board {
return &Board{Cells: cells}
}
func BenchmarkBacktrack(b *testing.B) {
for i := 0; i < b.N; i++ {
scratch = NewBoard(exampleBoard.Cells)
scratch.Backtrack()
}
func BenchmarkNewBoard(b *testing.B) {
for i := 0; i < b.N; i++ {
scratch = NewBoard(exampleBoard.Cells)
}
另请注意scratch
变量的使用。尝试在基准测试循环内创建循环局部变量可能会导致编译器根据是否存在副作用来优化调用NewBoard()
。对于奇偶校验,您需要在两个基准测试中使用scratch
变量。
答案 1 :(得分:1)
并且不会花费函数调用影响基准的少量时间吗?
他们当然会。 for
循环也是如此,它包含在基准测试中。加上调用copy.Backtrack
函数的开销。但问题是,这应该都是无关紧要的,除非你在一个单一的操作基准测试时间为纳秒(在这种情况下你不应该)。创建一个空板可能是一个微不足道的操作,所以我根本不会触及计时器。如果它不是微不足道的,那么你做得对 - 请致电StopTimer
。这正是它被发明的原因:
StopTimer停止测试计时。这可用于在执行您不想测量的复杂初始化时暂停计时器。