了解GoLang分析输出

时间:2018-02-19 23:22:31

标签: go optimization apache-kafka profiling sarama

某些背景信息:

我正在尝试调试GoGRPC服务器,特定的API调用似乎需要花费很多时间。这个调用会对Kafka进行一些读取(比方说10-20),所以我预计它需要一些时间,而不是那么多。

1 API调用大约需要1-3秒才能完成,但如果我在脚本中进行40次api调用,则需要将近30秒才能完成所有调用。但它并没有像我预期的那样“同时”完成它们,第一个需要花费5秒钟,而后来每秒花费1秒左右。

需要29秒才能同时响应所有40个请求。这会导致API调用者在请求耗时太长时超时。

我正试图分析CPU,看看我花时间在哪里。但我是新手,并且go profiler的输出没有多大意义。

我使用go tool pprof生成了图表,但在解释输出方面遇到了一些麻烦。

CPU调用图

  1. 是一个描述时间,类型,构建ID等的框,此框中的Duration是描述CPU运行的总时间的?不包括wiat时间
  2. 有两种类型的边,实线和虚线。有什么不同?边缘上标记的时间是什么意思?
  3. 箭头的方向是否意味着呼唤方向?例如函数A调用B,在图表上它将是A - > B'
  4. 每个顶点在底部有一个时间,例如在0.49s(45.79%)中0.01s(0.93%),这个时间是什么意思?
  5. 阻止个人资料

    1. 与上面的#4相同,在边缘和顶点上有时间。这是什么意思?
    2. 编辑:

      我的服务器所做的是从kafka流中检索一些数据。我已经确定了什么是慢的,我写了一个只有kafka调用函数的脚本。这是脚本和块分析图。

      对pafka的每次消耗大约需要50-100ms,但由于大部分时间都花在了IO上,我希望API的吞吐量实际上非常高,但实际情况并非如此。如果我拨打100个电话,大约需要3秒钟,如果我拨打400则需要大约10秒钟。试图了解如何加快API的吞吐量

      func main() {
      
          f, _ := os.Create("cpu.prof")
          pprof.StartCPUProfile(f)
          defer pprof.StopCPUProfile()
      
          block, _ := os.Create("block.prof")
          runtime.SetBlockProfileRate(1)
          p := pprof.Lookup("block")
          defer p.WriteTo(block, 0)
      
          var wg sync.WaitGroup
          wg.Add(messageCount)
          for i := 0; i < messageCount; i++ {
              go func() {
                  // consume()
                  withConsumer()
                  wg.Done()
              }()
      
          }
      
          wg.Wait()
      }
      
      var servers = []string{"kafka-1", "kafka-2", "kafka-3"}
      
      var count = 0
      var partition = int32(0)
      
      func consume() {
      
          index := count
          t := time.Now()
          count++
          fmt.Println("starting consume", index)
          defer func() {
              fmt.Println("consume ", index, "took", time.Since(t).String())
          }()
      
          consumer, err := sarama.NewConsumer(servers, nil)
          if err != nil {
              panic(err)
          }
          var max, min int64
          max = 1431401
          min = 2
      
          defer func() {
              consumer.Close()
          }()
      
          pc, err := consumer.ConsumePartition("source-topic", partition, rand.Int63n(max-min)+min)
          if err != nil {
              panic(err)
          }
      
          defer func() {
              pc.Close()
          }()
      
          signals := make(chan os.Signal, 1)
          signal.Notify(signals, os.Interrupt)
      
          select {
          case msg := <-pc.Messages():
              fmt.Println("msg: ", len(msg.Value))
          case <-signals:
              return
          }
      }
      

      enter image description here 谢谢,

1 个答案:

答案 0 :(得分:0)

<块引用>
  1. 有一个框来描述时间、类型、构建 ID 等。 这个方框是在描述 CPU 运行的总时间吗?不是 包括等待时间

正确。 https://golang.org/doc/diagnostics#profiling 说:

<块引用>

cpu:CPU 配置文件决定程序在何处花费时间 主动消耗 CPU 周期(与睡眠或等待时相反) 用于 I/O)。

<块引用>
  1. 边缘有两种类型,实线和虚线。什么是 区别?边缘标记的时间是什么意思?

https://github.com/google/pprof/issues/493 表示“点/虚线表示中间节点已被删除。删除节点是为了使图形足够小以进行可视化。”

https://gperftools.github.io/gperftools/cpuprofile.html 表示“每条边都标有被调用者代表调用者花费的时间。”

<块引用>
  1. 箭头的方向是指呼叫方向吗?例如 函数 A 调用 B,在图上它将是 A -> B?

是的。

<块引用>
  1. 每个顶点都有 底部的时间,例如0.01s(0.93%) 出 0.49s(45.79%),这个时间是什么意思?

第一次是当地时间。第二次是累计时间。 https://gperftools.github.io/gperftools/cpuprofile.html 详细说明:

<块引用>

“本地”时间是直接执行指令所花费的时间 包含在程序中(以及任何其他程序中 内联到程序中)。 “累计”时间是 “本地”时间和在任何被调用者中花费的时间。如果累计时间 与当地时间相同,不打印。