【发布时间】:2021-12-28 15:08:01
【问题描述】:
在 golang 网络服务器中,我想测量一些 http 控制器所花费的时间。我在调用控制器函数之前调用time.Now(),在控制器函数返回之后调用time.Since()。但是如果它有需要 1 秒的长远程 io 请求,或者进程被限制,或者控制器与 goroutine 并行 - 那么那个时间将不是我想要的。
如果我们假设类比为 bash time 命令 - 那么我将获得 real 使用此技术的时间:
time go build
real 0m5,204s
user 0m12,012s
sys 0m2,043s
如何在 golang 程序(最好使用标准包)中测量函数运行(最好是 goroutine 及其分叉子代)的 user 和 sys 时间?
这是我的分析器实现。如何使用每个 goroutine 的 sys 和用户时间来扩展它?
const HeaderCost = "Cost"
// Timed middleware will set Cost header in http response
func Timed(h http.Handler) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(&responseWriterWithTimer{
ResponseWriter: w,
headerWritten: false,
startedAt: time.Now(),
}, r)
})
}
type responseWriterWithTimer struct {
http.ResponseWriter
headerWritten bool
startedAt time.Time
}
func (w *responseWriterWithTimer) WriteHeader(statusCode int) {
w.Header().Set(
HeaderCost,
strconv.FormatFloat(
time.Since(w.startedAt).Seconds(),
'g',
64,
64,
),
)
w.ResponseWriter.WriteHeader(statusCode)
w.headerWritten = true
}
func (w *responseWriterWithTimer) Write(b []byte) (int, error) {
if !w.headerWritten {
w.WriteHeader(http.StatusOK)
}
return w.ResponseWriter.Write(b)
}
【问题讨论】:
-
您可以使用github.com/shirou/gopsutil 之类的方法在进程级别测量 CPU 时间。在我看来,目前在 Go 例程级别执行此操作是不可能的。如果您精确测量您的处理程序而不是其他任何东西,那么测量实时应该没问题。
-
@Zyl 进程级别包括所有线程,其中每个线程运行未知数量的 goroutine。所以这不是一个正确的衡量标准。