Golang中如何测量快速操作的执行时间
Golang中如何测量快速操作的执行时间 你好, 我想测量一个耗时极短的子程序的执行时间。一个简单的例子:
package main
import (
"fmt"
"time"
)
func main() {
timer:= time.Now()
fmt.Println("Hello, playground")
fmt.Printf("(Execution time: %s) |", time.Since(timer))
}
但这总是返回 0 秒,然而我需要以某种方式测量它(即需要更高的分辨率)。有什么建议吗?谢谢!
6 回复
是的,我的系统运行的是Windows。我将在Ubuntu上运行它,看看结果如何。也会研究一下基准测试……
更多关于Golang中如何测量快速操作的执行时间的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我确认在Ubuntu系统上运行该代码会返回微秒级的数值,而不仅仅是零。如果能知道Windows系统是否有修复方法就更好了。
不,据我从谷歌搜索结果的理解,目前对此没有修复方法。即使是高分辨率计时器,每个节拍的精度也不会高于0.5毫秒。
如果这是用于基准测试,请使用基准测试功能:https://golang.org/pkg/testing/#hdr-Benchmarks
如果不是用于基准测试,并且你使用的系统计时器分辨率较低(例如 Windows),我想这个时间足够短,不必担心。
对我来说并非如此:
$ go run main.go
Hello, playground
(Execution time: 29.073µs) |
$ go run main.go
Hello, playground
(Execution time: 21.639µs) |
$ go run main.go
Hello, playground
(Execution time: 21.575µs) |
$ go run main.go
Hello, playground
(Execution time: 20.104µs) |
$ go run main.go
Hello, playground
(Execution time: 22.327µs) |
也许你是在一个时钟精度不够的系统上测试的?或者你是在 Go Playground 上测试的,那里的时钟不会前进?
在Go中测量微秒或纳秒级操作的执行时间,需要使用time包的高精度方法。以下是几种解决方案:
1. 使用 time.Since() 配合纳秒精度
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
// 快速操作示例
sum := 0
for i := 0; i < 1000; i++ {
sum += i
}
elapsed := time.Since(start)
fmt.Printf("执行时间: %v\n", elapsed)
fmt.Printf("纳秒: %d ns\n", elapsed.Nanoseconds())
fmt.Printf("微秒: %.3f µs\n", float64(elapsed.Nanoseconds())/1000)
fmt.Printf("毫秒: %.6f ms\n", float64(elapsed.Nanoseconds())/1000000)
}
2. 使用 time.Now().UnixNano() 直接获取纳秒时间戳
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now().UnixNano()
// 需要测量的快速操作
_ = make([]byte, 1024)
end := time.Now().UnixNano()
elapsed := end - start
fmt.Printf("执行时间: %d ns\n", elapsed)
fmt.Printf("执行时间: %.3f µs\n", float64(elapsed)/1000)
}
3. 多次执行取平均值(针对极短操作)
package main
import (
"fmt"
"time"
)
func fastOperation() {
// 模拟快速操作
_ = 42 * 42
}
func main() {
iterations := 1000000
totalTime := time.Duration(0)
for i := 0; i < iterations; i++ {
start := time.Now()
fastOperation()
totalTime += time.Since(start)
}
avgTime := totalTime / time.Duration(iterations)
fmt.Printf("平均执行时间: %v\n", avgTime)
fmt.Printf("平均执行时间: %d ns\n", avgTime.Nanoseconds())
}
4. 使用 runtime.nanotime() 内部函数(最高精度)
package main
import (
"fmt"
"time"
_ "unsafe"
)
//go:linkname nanotime runtime.nanotime
func nanotime() int64
func main() {
start := nanotime()
// 需要测量的操作
var x int64
for i := 0; i < 100; i++ {
x += int64(i)
}
end := nanotime()
elapsed := end - start
fmt.Printf("执行时间: %d ns\n", elapsed)
fmt.Printf("执行时间: %.3f µs\n", float64(elapsed)/1000)
// 对比标准方法
stdStart := time.Now()
for i := 0; i < 100; i++ {
x += int64(i)
}
stdElapsed := time.Since(stdStart)
fmt.Printf("标准方法: %v\n", stdElapsed)
}
5. 实际应用示例:测量函数调用开销
package main
import (
"fmt"
"time"
)
func measureShortOperation() {
start := time.Now()
// 需要测量的快速操作
result := 0
for i := 0; i < 100; i++ {
result += i * i
}
_ = result // 防止编译器优化
elapsed := time.Since(start)
if elapsed < time.Microsecond {
fmt.Printf("执行时间: %d ns\n", elapsed.Nanoseconds())
} else if elapsed < time.Millisecond {
fmt.Printf("执行时间: %.3f µs\n", float64(elapsed.Nanoseconds())/1000)
} else {
fmt.Printf("执行时间: %v\n", elapsed)
}
}
func main() {
// 测量多次以减少误差
for i := 0; i < 5; i++ {
measureShortOperation()
}
}
关键点:
time.Since()返回的是time.Duration类型,默认字符串格式可能显示为0s,但实际有纳秒精度- 使用
.Nanoseconds()方法获取纳秒数值 - 对于极短操作,建议多次执行取平均值
- 注意编译器优化可能影响测量结果,可使用
_ = result防止优化 - 在Linux/macOS上,Go的
time.Now()通常使用clock_gettime(CLOCK_MONOTONIC, ...),精度可达纳秒级
测量结果显示为0秒是因为默认的字符串格式只显示到秒,实际可以通过上述方法获取更高精度的测量结果。

