Go (推送模式)
我们的 Go Profiler 是一款尖端工具,旨在优化 Golang 应用。通过与 Pyroscope 集成,Profiler 为开发者提供了其 Go 代码库的深入视图,从而实现实时性能分析。这个强大的工具对于找出低效之处、精简代码执行并确保 Go 应用的最佳性能至关重要。
Pyroscope 使用标准的 runtime/pprof
包来收集性能分析数据。有关详细信息,请参阅官方文档。
注意
有关 Go 支持的性能分析类型列表,请参阅可用性能分析类型。
开始之前
要捕获和分析性能分析数据,您需要一个托管的 Pyroscope OSS 服务器或一个带有 Grafana Cloud Profiles 的托管 Pyroscope 实例(需要免费的 Grafana Cloud 账户)。
Pyroscope 服务器可以是用于开发的本地服务器,也可以是用于生产的远程服务器。
配置 Go 客户端
要开始对 Go 应用进行性能分析,您需要在应用中包含 Go 模块
go get github.com/grafana/pyroscope-go
注意
如果您倾向于使用拉取模式,可以通过以下方式实现:
将以下代码添加到您的应用中
package main
import "github.com/grafana/pyroscope-go"
func main() {
// These 2 lines are only required if you're using mutex or block profiling
// Read the explanation below for how to set these rates:
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(5)
pyroscope.Start(pyroscope.Config{
ApplicationName: "simple.golang.app",
// replace this with the address of pyroscope server
ServerAddress: "http://pyroscope-server:4040",
// you can disable logging by setting this to nil
Logger: pyroscope.StandardLogger,
// you can provide static tags via a map:
Tags: map[string]string{"hostname": os.Getenv("HOSTNAME")},
ProfileTypes: []pyroscope.ProfileType{
// these profile types are enabled by default:
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,
// these profile types are optional:
pyroscope.ProfileGoroutines,
pyroscope.ProfileMutexCount,
pyroscope.ProfileMutexDuration,
pyroscope.ProfileBlockCount,
pyroscope.ProfileBlockDuration,
},
})
// your code goes here
}
或者,如果您想对性能分析过程有更多控制,可以手动处理 profiler 的初始化和终止
profiler, err := pyroscope.Start(pyroscope.Config{
// omitted for brevity
})
if err != nil {
// the only reason this would fail is if the configuration is not valid
log.Fatalf("failed to start Pyroscope: %v", err)
}
defer profiler.Stop()
// your code goes here
}
如果您需要确保在应用退出前发送最后一个 profile,则可能需要此方法。
为您的应用添加性能分析标签
您可以为性能分析数据添加标签(labels)。这些标签可用于在 UI 中过滤数据。有一个与 Go 原生 pprof API 一致的自定义 API
// these two ways of adding tags are equivalent:
pyroscope.TagWrapper(context.Background(), pyroscope.Labels("controller", "slow_controller"), func(c context.Context) {
slowCode()
})
pprof.Do(context.Background(), pprof.Labels("controller", "slow_controller"), func(c context.Context) {
slowCode()
})
Mutex 性能分析
Mutex 性能分析对于查找应用内的竞争来源非常有用。它帮助您找出哪些 mutex 被哪些 goroutine 持有。
要启用 mutex 性能分析,您需要将以下代码添加到您的应用中
runtime.SetMutexProfileFraction(rate)
rate
参数控制在 mutex profile 中报告的 mutex 竞争事件的比例。平均而言,每 1/rate 个事件会被报告。
Block 性能分析
Block 性能分析让您可以分析程序在等待以下阻塞操作上花费了多少时间,例如:
- select
- channel send/receive
- semacquire
- notifyListWait
要启用 block 性能分析,您需要将以下代码添加到您的应用中
runtime.SetBlockProfileRate(rate)
rate
参数控制在 blocking profile 中报告的 goroutine 阻塞事件的比例。profiler 的目标是平均每阻塞 rate 纳秒采样一个阻塞事件。
将数据发送到 Pyroscope OSS 或 Grafana Cloud Profiles
要配置 Golang SDK 将数据发送到 Pyroscope,请将占位符 <URL>
替换为相应的服务器 URL。这可以是 Grafana Cloud URL,也可以是您自己的自定义 Pyroscope 服务器 URL。
如果您需要将数据发送到 Grafana Cloud,则必须配置 HTTP Basic 认证。将 <User>
替换为您的 Grafana Cloud stack 用户,将 <Password>
替换为您的 Grafana Cloud API 密钥。
如果您的 Pyroscope 服务器启用了多租户,您需要配置一个租户 ID。将 <TenantID>
替换为您的 Pyroscope 租户 ID。
pyroscope.Start(pyroscope.Config{
ApplicationName: "example.golang.app",
ServerAddress: "<URL>",
// Optional HTTP Basic authentication
BasicAuthUser: "<User>",
BasicAuthPassword: "<Password>",
// Optional Pyroscope tenant ID (only needed if using multi-tenancy). Not needed for Grafana Cloud.
// TenantID: "<TenantID>",
ProfileTypes: []pyroscope.ProfileType{
pyroscope.ProfileCPU,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileInuseSpace,
pyroscope.ProfileAllocSpace,
},
})
选项:使用 DisableGCRuns 处理内存使用量增加的问题
当追踪大量对象时,Pyroscope 可能需要额外的资源。例如,索引大量数据的 Go 服务需要更多内存。这种追踪可能导致更高的 CPU 使用率和潜在的 CPU 节流。
您可以在 Go 配置中使用 DisableGCRuns
来禁用自动运行时。如果此标志被激活,GC 运行会减少,从而消耗的 CPU 资源也会减少。然而,堆 profile 可能会不太精确。
背景
在 Go 的 pprof 堆性能分析中,强制垃圾回收(GC)通过移除未回收的对象来确保精确的内存使用快照。如果没有这一步,堆 profile 可能包含已分配但不再使用的内存——那些仅仅因为尚未被回收而停留在内存中的对象。这可能会掩盖或模拟内存泄漏,并在 profile 中引入偏差,使分析复杂化。因此,Pyroscope 默认在每次收集堆 profile 时强制进行 GC。
然而,在某些情况下,强制 GC 会增加 CPU 使用率,特别是当堆中有大量存活对象时。runtime.GC
函数在 CPU profile 中的出现反映了这个问题。如果问题已经显现,并且堆 profile 中的一些不准确性是可以接受的,那么建议禁用此选项以避免性能下降。
激活 DisableGCRuns
在 pyroscope.Start(pyroscope.Config)
块中添加 DisableGCRuns: true
。
pyroscope.Start(pyroscope.Config{
ApplicationName: "example.golang.app",
ServerAddress: "<URL>",
// Disable automatic runtime.GC runs between getting the heap profiles.
DisableGCRuns: true,
Golang 性能分析示例
查看以下资源,了解更多关于 Golang 性能分析的信息
- Golang 示例
- Golang Demo 展示带有标签的 golang 示例