您的位置:首页 > 娱乐 > 八卦 > 南昌百度seo_什么是网络营销的微观环境_微信广点通广告平台_深圳企业seo

南昌百度seo_什么是网络营销的微观环境_微信广点通广告平台_深圳企业seo

2025/4/19 16:53:50 来源:https://blog.csdn.net/u011634421/article/details/147202135  浏览:    关键词:南昌百度seo_什么是网络营销的微观环境_微信广点通广告平台_深圳企业seo
南昌百度seo_什么是网络营销的微观环境_微信广点通广告平台_深圳企业seo

Go 开发者在使用 testing包编写基准测试用例时,如果不注意,可能会遇到各种陷阱。这些陷阱,导致基准测试结果不准确。Go1.24 版本引入了一种新的基准测试编写方式,它同样易用,并且可以帮助规避编写基准测试时的一些坑。

Go 1.24 版本推荐使用 testing.B.Loop代替 testing.B.N来编写基准测试用例。

Go1.24 版本前,我们使用 b.N 来编写基准测试用例,例如:

func Benchmark(b *testing.B) {for range b.N {... 要测量的代码 ...}
}

改用b.Loop仅需要微不足道的改动:

func Benchmark(b *testing.B) {for b.Loop() {... 要测量的代码 ...}
}

testing.B.Loop有很多优点:

  • 可以防止基准测试循环内的不当编译优化;
  • 可以自动将设置和清理部分代码耗时从基准测试时间统计中剔除;
  • 代码不应意外地依赖于总迭代次数或当前迭代。

上述这些优点都是在使用 b.N编写基准测试代码时易犯的错误,这些错误会导致基准测试不准确。除了上述优点之外,b.Loop风格的基准测试,还能再更短的时间执行完。

接下来,我们来看下testing.B.Loop的优势以及如何有效地使用它。

旧基准测试循环问题

在 Go 1.24 之前,大部分的基准测试用例结构简单。但是复杂的测试用例,却需要很小心的编写:

func Benchmark(b *testing.B) {... setup ...b.ResetTimer() // 如果设置可能很昂贵for range b.N {... 代码测量 ...... 使用汇点或累积防止未用代码消除 ...}b.StopTimer() // 如果清理或报告可能很昂贵... 清理 ...... 报告 ...
}

如果设置 (setup)或清理 (cleanup)逻辑复杂,耗时较久,为了避免这些准备性的逻辑参与到核心代码的耗时统计中,需要使用ResetTimerStopTimer 方法,将这些时间剔除掉。但是真正开发的过程中, 可能有一些开发者会遗漏这些逻辑。即使开发者没有遗漏,也很难判断设置或清理过程是否“足够耗时”到需要使用它们。

还有一个更微妙的陷阱,需要更深入的理解(示例源代码):

func isCond(b byte) bool {if b%3 == 1 && b%7 == 2 && b%17 == 11 && b%31 == 9 {return true}return false
}func BenchmarkIsCondWrong(b *testing.B) {for range b.N {isCond(201)}
}

在这个例子中,用户可能会观察到 isCond 在亚纳秒级别的时间内执行。CPU 的速度很快,但并没有快到这个程度!这个看似异常的结果源于 isCond 被内联处理,并且由于其结果从未被使用,编译器将其视为无效代码而进行消除。

因此,这个基准测试根本没有测量 isCond。它测量的是进行无操作所需的时间。在这种情况下,亚纳秒的结果是一个明显的警示,但在更复杂的基准测试中,部分无效代码消除可能导致看起来合理但实际上并未测量预期内容的结果。

testing.B.Loop可以带来哪些好处?

b.N 风格的基准测试不同,testing.B.Loop 能够跟踪其首次调用时间以及基准测试的最终迭代结束时刻。循环开始时的 b.ResetTimer 和结束时的 b.StopTimer 被整合进 testing.B.Loop,消除了手动管理基准测试计时器以进行初始化和清理代码的开发步骤。

另外,Go 编译器现在可以探测到只调用 testing.B.Loop 时的循环,并阻止 testing.B.Loop 内的代码死循环。

testing.B.Loop 的另一个优点是其一次性快速提升的方法。对于 b.N 风格的基准测试,测试包必须多次调用基准测试函数,并使用不同的 b.N 值逐步增加,直到测量时间达到一个阈值。相比之下,b.Loop 可以简单地运行基准测试循环,直到达到时间阈值,只需调用基准测试函数一次。

b.N 风格循环的某些限制仍适用于 b.Loop 风格的循环。用户仍需在必要时负责在基准测试循环中管理计时器。(示例源)

func BenchmarkSortInts(b *testing.B) {ints := make([]int, N)for b.Loop() {b.StopTimer()fillRandomInts(ints)b.StartTimer()slices.Sort(ints)}
}

在这个例子中,为了测试 slices.Sort 方法的就地排序性能,每次迭代都需要一个随机初始化的数组。开发菏泽仍需在这些情况下手动管理计时器。

此外,基准测试函数体中仍需要只有一个这样的循环(b.N风格循环不能与b.Loop风格循环共存),并且循环的每次迭代应该做相同的事情。

何时使用

testing.B.Loop 方法,是从 Go 1.24 版本起,编写基准测试的首选方式。使用示例如下:

func Benchmark(b *testing.B) {... 设置 ...for b.Loop() {// 可选的循环内部设置/清理计时器控制... 要测量的代码 ...}... 清理 ...
}
  • 知识星球:令飞编程。10+ 高质量体系课( Go、云原生、AI Infra)、15+ 高质量实战项目,P8 技术专家助你提高技术天花板,冲击百万年薪!
  • 我公众号:令飞编程,分享 Go、云原生、AI Infra 相关技术。回复「资料」免费下载 Go、云原生、AI 等学习资料;
  • 哔哩哔哩:令飞编程 ,以视频、直播的形式,分享技术、职场、课程、面经等;

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com