跳转至

Profiling Golang

Go 内置了性能分析 (Profiling) 工具 pprof,可以采集程序运行中的性能数据,可通过以下两种方式使用:

  • runtime/pprof: 通过编程方式,自定义采集运行数据,然后保存分析
  • net/http/pprof: 调用 runtime/pprof,封装成接口,通过 HTTP Server 的方式对外提供性能数据

性能数据主要包括如下:

  • goroutine: 运行的 Goroutine 的调用栈分析
  • heap: 活跃对象的内存分配情况
  • allocs: 所有对象的内存分配情况
  • threadcreate: OS 线程创建分析
  • block: 阻塞分析
  • mutex: 互斥锁分析

收集到的数据,可以通过官方 pprof 工具进行分析。

DataKit 可通过主动拉取 (pull) 或被动推送 (push) 的方式来获取这些数据。

push 方式

DataKit 配置

DataKit 开启 profile 采集器,注册 profile http 服务。

[[inputs.profile]]
  ## profile Agent endpoints register by version respectively.
  ## Endpoints can be skipped listen by remove them from the list.
  ## Default value set as below. DO NOT MODIFY THESE ENDPOINTS if not necessary.
  endpoints = ["/profiling/v1/input"]

Go 应用配置

集成 dd-trace-go,采集应用性能数据并发送至 DataKit。 代码参考如下:

package main

import (
    "log"
    "time"

    "gopkg.in/DataDog/dd-trace-go.v1/profiler"
)

func main() {
    err := profiler.Start(
        profiler.WithService("dd-service"),
        profiler.WithEnv("dd-env"),
        profiler.WithVersion("dd-1.0.0"),
        profiler.WithTags("k:1", "k:2"),
        profiler.WithAgentAddr("localhost:9529"), // DataKit url
        profiler.WithProfileTypes(
            profiler.CPUProfile,
            profiler.HeapProfile,
            // The profiles below are disabled by default to keep overhead
            // low, but can be enabled as needed.

            // profiler.BlockProfile,
            // profiler.MutexProfile,
            // profiler.GoroutineProfile,
        ),
    )

    if err != nil {
        log.Fatal(err)
    }
    defer profiler.Stop()

    // your code here
    demo()
}

func demo() {
    for {
        time.Sleep(100 * time.Millisecond)
        go func() {
            buf := make([]byte, 100000)
            _ = len(buf)
            time.Sleep(1 * time.Hour)
        }()
    }
}

运行该程序后,DDTrace 会定期(默认 1 分钟一次)将数据推送给 DataKit。

生成性能指标

DataKit 自 Version-1.39.0 开始支持从 dd-trace-go 的输出中抽取一组 Go 运行时的相关指标,该组指标被置于 profiling_metrics 指标集下,下面列举其中部分指标加以说明:

Tags & Fields Description
language
(tag)
Language of current profile
host
(tag)
Hostname of current profile
service
(tag)
Service name of current profile
env
(tag)
Env settings of current profile
version
(tag)
Version of current profile
prof_go_cpu_cores Number of CPU cores consumed
Unit: core
prof_go_cpu_cores_gc_overhead Number of CPU cores used for garbage collection
Unit: core
prof_go_alloc_bytes_per_sec Memory allocation rate per second
Unit: byte
prof_go_frees_per_sec Number of objects freed by GC per second
Unit: count
prof_go_heap_growth_bytes_per_sec Heap memory growth rate per second
Unit: byte
prof_go_allocs_per_sec Memory allocation operations per second
Unit: count
prof_go_alloc_bytes_total Total memory allocated during a single profiling period (dd-trace defaults to 60-second collection cycles)
Unit: byte
prof_go_blocked_time Total time goroutines were blocked during a single profiling period
Unit: nanosecond
prof_go_mutex_delay_time Total time spent waiting for locks during a single profiling period
Unit: nanosecond
prof_go_gcs_per_sec Number of GC runs per second
Unit: count
prof_go_max_gc_pause_time Maximum single pause duration caused by GC during a profiling period
Unit: nanosecond
prof_go_gc_pause_time Total pause time caused by GC during a profiling period
Unit: nanosecond
prof_go_num_goroutine Current total number of goroutines
Unit: count
prof_go_lifetime_heap_bytes Total memory size occupied by live objects in the heap
Unit: byte
prof_go_lifetime_heap_objects Total number of live objects in the heap
Unit: count
Tips

该功能默认开启,如果不需要可以通过修改采集器的配置文件 <DATAKIT_INSTALL_DIR>/conf.d/profile/profile.conf 把其中的配置项 generate_metrics 置为 false 并重启 DataKit.

[[inputs.profile]]

...

## set false to stop generating apm metrics from ddtrace output.
generate_metrics = false

Pull 方式

Go 应用开启 Profiling

应用中开启 Profiling 只需要引用 pprof 包即可,参考如下:

package main

import (
  "net/http"
   _ "net/http/pprof"
)

func main() {
    http.ListenAndServe(":6060", nil)
}

运行代码后,可通过 http://localhost:6060/debug/pprof/heap?debug=1 来查看是否开启成功。

  • Mutex 和 Block 性能分析

默认情况下,mutex 和 block 性能采集并未开启,如果需要开启,可添加如下代码:

var rate = 1

// enable mutex profiling
runtime.SetMutexProfileFraction(rate)

// enable block profiling
runtime.SetBlockProfileRate(rate)

rate 设置采集频率,即 1/rate 的事件被采集, 如设置为 0 或小于 0 的数值,是不进行采集的。

DataKit 配置

开启 Profile 采集器,进行如下设置 [[inputs.profile.go]]

[[inputs.profile]]
  ## profile Agent endpoints register by version respectively.
  ## Endpoints can be skipped listen by remove them from the list.
  ## Default value set as below. DO NOT MODIFY THESE ENDPOINTS if not necessary.
  endpoints = ["/profiling/v1/input"]

  ## set true to enable election
  election = true

 ## go pprof config
[[inputs.profile.go]]
  ## pprof url
  url = "http://localhost:6060"

  ## pull interval, should be greater or equal than 10s
  interval = "10s"

  ## service name
  service = "go-demo"

  ## app env
  env = "dev"

  ## app version
  version = "0.0.0"

  ## types to pull 
  ## values: cpu, goroutine, heap, mutex, block
  enabled_types = ["cpu","goroutine","heap","mutex","block"]

[inputs.profile.go.tags]
  # tag1 = "val1"
Note

如果不需要开启 Profile 的 HTTP 服务,可将 endpoints 字段注释掉。

字段说明

  • url: 上报地址,如 http://localhost:6060
  • interval: 采集间隔时间,最小 10s
  • service: 服务名称
  • env: 应用环境类型
  • version: 应用的版本
  • enabled_types: 性能类型,如 cpu, goroutine, heap, mutex, block

配置好 Profile 采集器,启动或重启 DataKit,一段时间后即可在观测云中心查看 Go 的性能数据。

文档评价

文档内容是否对您有帮助? ×