How timing function execution works in go?

huangapple go评论78阅读模式
英文:

How timing function execution works in go?

问题

我正在尝试计时执行一个函数,但它总是返回0ns,这很难相信。我在中间添加了1ns的睡眠,但它会产生奇怪的结果(当取消注释时)。以下是代码:

func pow2(base, exponent int64) int64 {
	var result int64 = 1
	for ; exponent > 0; exponent >>= 1 {
		result *= base
	}
	return result
}
func Test_pow2(*testing.T) {
	var base, exponent, n, expected int64 = 2, 256, 0, 0
	var start time.Time
	var duration time.Duration

	start = time.Now()
	n = fastExponentiationAlgorithm(base, exponent)
	//time.Sleep(1 * time.Nanosecond)
	duration = time.Since(start)
	expected = math.Pow(base, exponent)
	if n != expected {
		fmt.Errorf("expected %+v but got %+v", expected, n)
	} else {
		fmt.Printf("pow2(%+v, %+v) executed in %dns\n", base, exponent, duration / time.Nanosecond)
	}
}

希望有人能指出我的错误,谢谢。

编辑:根据Adrianhymns for disco的建议,生成了一个基准测试,结果如下:

func Benchmark_pow2(b *testing.B) {
	var base, exponent, n, expected int64 = 2, 10, 0, 0

	expected = math.Pow(base, exponent)

	b.ResetTimer()
	n = pow2(base, exponent)
	b.StopTimer()

	if n != expected {
		b.Errorf("expected %d but got %d", expected, n)
	}
}

执行后,生成了以下输出:

Benchmark_pow2
    test1_test.go:44: expected 20 but got 16
--- FAIL: Benchmark_pow2

在这里发生了什么?为什么会以这种方式失败?

英文:

I'm trying to time the execution of a function but it always returns 0ns, which is hard to believe. Added a 1ns sleep in between but it does strange things (when uncommented). Here is the code:

func pow2(base, exponent int64) int64 {
	var result int64 = 1
	for ; exponent > 0; exponent >>= 1 {
		result *= base
	}
	return result
}
func Test_pow2(*testing.T) {
	var base, exponent, n, expected int64 = 2, 256, 0, 0
	var start time.Time
	var duration time.Duration

	start = time.Now()
	n = fastExponentiationAlgorithm(base, exponent)
	//time.Sleep(1 * time.Nanosecond)
	duration = time.Since(start)
	expected = math.Pow(base, exponent)
	if n != expected {
		fmt.Errorf("expected %+v but got %+v", expected, n)
	} else {
		fmt.Printf("pow2(%+v, %+v) executed in %dns\n", base, exponent, duration / time.Nanosecond)
	}
}

Hopefully someone can point out my mistake,
regards.


Edit: A benchmark was generated, as suggested by Adrian and hymns for disco, which resulted as the following:

func Benchmark_pow2(b *testing.B) {
	var base, exponent, n, expected int64 = 2, 10, 0, 0

	expected = math.Pow(base, exponent)

	b.ResetTimer()
	n = pow2(base, exponent)
	b.StopTimer()

	if n != expected {
		b.Errorf("expected %d but got %d", expected, n)
	}
}

After executing it, this output is generated:

Benchmark_pow2
    test1_test.go:44: expected 20 but got 16
--- FAIL: Benchmark_pow2

What is happening in here? why is it failing in this way?

答案1

得分: 3

时间包的有效精度并不是很高。即使值达到了“纳秒精度”,这并不意味着时间实际上每纳秒更新一次。根据我的测试,当前时间的分辨率实际上是100纳秒,并且大约每0.5毫秒更新一次。这很可能会因操作系统、硬件和其他因素而有所不同。

如果你想正确计时,可以阅读测试包中的基准测试。基准测试提供了更好的精度,因为它们在循环中多次运行你的代码,以获取平均执行时间。这样可以测量那些在没有聚合时太小的时间(就像你的情况)。

英文:

The effective precision of the time package is not that great. Even though the value goes to "nanosecond precision", that doesn't mean the time actually updates every nanosecond. From my own testing, the resolution of the current time is effectively 100 nanoseconds and only updates about every 0.5 milliseconds. This will most likely vary depending on your OS, hardware, and other factors.

If you want to time things the right way, read about benchmarks in the testing package. Benchmarks offer better precision because they run your code multiple times in a loop, to get the average execution time. This allows you to measure times which would be too small when not aggregated (like in your case).

huangapple
  • 本文由 发表于 2021年6月8日 21:25:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/67887891.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定