Golang 性能测试 (3) 协程追踪术

栏目: IT技术 · 发布时间: 4年前

内容简介:本文简单介绍 golang 如何做跟踪刨析。对于绝大部分服务,跟踪刨析是用不到的。但是如果遇到了下面问题,可以不妨一试:坦白的讲,通过跟踪刨析可以看到每个协程在某一时刻在干什么。

本文简单介绍 golang 如何做跟踪刨析。

简介

对于绝大部分服务,跟踪刨析是用不到的。但是如果遇到了下面问题,可以不妨一试:

  • 怀疑哪个协程慢了
  • 系统调用有问题
  • 协程调度问题 (chan 交互、互斥锁、信号量等)
  • 怀疑是 gc (Garbage-Collect) 影响了服务性能
  • 网络阻塞
  • 等等

坦白的讲,通过跟踪刨析可以看到每个协程在某一时刻在干什么。

做跟踪刨析,首先需要获取trace 数据。可以通过代码中插入trace, 或者上节提到的通过pprof 下载即可。

Example

Code

下面通过代码直接插入的方式来获取trace. 内容会涉及到网络请求,涉及协程异步执行等。

package main

import (
    "io/ioutil"
    "math/rand"
    "net/http"
    "os"
    "runtime/trace"
    "strconv"
    "sync"
    "time"
)


var wg sync.WaitGroup
var httpClient = &http.Client{Timeout: 30 * time.Second}

func SleepSomeTime() time.Duration{
    return time.Microsecond * time.Duration(rand.Int()%1000)
}

func create(readChan chan int) {
    defer wg.Done()
    for i := 0; i < 500; i++ {
        readChan <- getBodySize()
        SleepSomeTime()
    }
    close(readChan)
}

func convert(readChan chan int, output chan string) {
    defer wg.Done()
    for readChan := range readChan {
        output <- strconv.Itoa(readChan)
        SleepSomeTime()
    }
    close(output)
}

func outputStr(output chan string) {
    defer wg.Done()
    for _ = range output {
        // do nothing
        SleepSomeTime()
    }
}

// 获取taobao 页面大小
func getBodySize() int {
    resp, _ := httpClient.Get("https://taobao.com")
    res, _ := ioutil.ReadAll(resp.Body)
    _ = resp.Body.Close()
    return len(res)
}

func run() {
    readChan, output := make(chan int), make(chan string)
    wg.Add(3)
    go create(readChan)
    go convert(readChan, output)
    go outputStr(output)
}

func main() {
    f, _ := os.Create("trace.out")
    defer f.Close()
    _ = trace.Start(f)
    defer trace.Stop()
    run()
    wg.Wait()
}

编译,并执行,然后启动trace;

[lipengfei5@localhost ~/blog]$ go build trace_example.go 
[lipengfei5@localhost ~/blog]$ ./trace_example
[lipengfei5@localhost ~/blog]$ go tool trace -http=":8000" trace_example trace.out 
2020/04/15 17:34:48 Parsing trace...
2020/04/15 17:34:50 Splitting trace...
2020/04/15 17:34:51 Opening browser. Trace viewer is listening on http://0.0.0.0:8000

然后打开浏览器,访问8000 端口即可。

Trace 功能

Golang 性能测试 (3) 协程追踪术

其中:

View trace:查看跟踪 (按照时间分段,上面我的例子时间比较短,所以没有分段)

Goroutine analysis:Goroutine 分析

Network blocking profile:网络阻塞概况

Synchronization blocking profile:同步阻塞概况

Syscall blocking profile:系统调用阻塞概况

Scheduler latency profile:调度延迟概况

User defined tasks:用户自定义任务

User defined regions:用户自定义区域

Minimum mutator utilization:最低 Mutator 利用率 (主要是GC 的评价标准, 暂时没搞懂)

goroutine 调度分析

下图包含了两种事件:

  1. 网络相关 main.create 触发网络写的协程,网络写操作的协程 writeLoop,然后等待网络返回。
  2. GC 相关操作

Golang 性能测试 (3) 协程追踪术

下面是web请求到数据,从epoll 中触发,然后readLoop协程响应,直接触发main.create 的协程得到执行。

Golang 性能测试 (3) 协程追踪术

当然我们也可以筛选协程做具体分析,从 Goroutine analysis 进入,选择具体的协程进行分析:

Golang 性能测试 (3) 协程追踪术

我们选择对 main.create 的协程做分析(这个协程略复杂,可以分析的东西比较多)

Golang 性能测试 (3) 协程追踪术

可以从图中看出,network 唤醒 readLoop 协程,进而readLoop 又通知了main.create 协程。

Golang 性能测试 (3) 协程追踪术

当然,我们也可以选择 main.convert 协程。可以看出协程被main.create 唤醒了(由于给chan 提供了数据)

Golang 性能测试 (3) 协程追踪术

除了可以分析goroutine 调度之外,还可以做网络阻塞分析,异步阻塞分析,系统调度阻塞分析,协程调度阻塞分析(下图)

Golang 性能测试 (3) 协程追踪术

自定义 Task 和 Region

当然,还可以指定task 和 Region 做分析,下面是官方举的例子:

//filepath:  src/runtime/trace/trace.go
ctx, task := trace.NewTask(ctx, "makeCappuccino")
trace.Log(ctx, "orderID", orderID)

milk := make(chan bool)
espresso := make(chan bool)

go func() {
        trace.WithRegion(ctx, "steamMilk", steamMilk)
        milk <- true
}()
go func() {
        trace.WithRegion(ctx, "extractCoffee", extractCoffee)
        espresso <- true
}()
go func() {
        defer task.End() // When assemble is done, the order is complete.
        <-espresso
        <-milk
        trace.WithRegion(ctx, "mixMilkCoffee", mixMilkCoffee)
}()

MMU 图

除此之外,还提供了Minimum Mutator Utilization 图 (mmu 图 )

mmu 图,数轴是服务可以占用cpu的百分比 (其他时间为gc操作)

Golang 性能测试 (3) 协程追踪术

从图中可以看出,在2ms之后,可利用的cpu逐步上升,直到接近100%.所以gc 毫无压力。

重点提醒

  1. 必须用chrome,并且高版本不行。我使用的是76.
  2. trace 的文件都比较大,几分钟可能上百兆,所以网络一定要好,或者使用本机做验证。
  3. 造作是 w 放大, s 缩小, a 左移, d 右移
  4. gc 的mmu 图解释 (备注下,还没有来得及看) https://www.cs.cmu.edu/~guyb/...

欢迎关注我们的微信公众号,每天学习 Go 知识

Golang 性能测试 (3) 协程追踪术

以上所述就是小编给大家介绍的《Golang 性能测试 (3) 协程追踪术》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入浅出Node.js

深入浅出Node.js

朴灵 / 人民邮电出版社 / 2013-12-1 / CNY 69.00

本书从不同的视角介绍了 Node 内在的特点和结构。由首章Node 介绍为索引,涉及Node 的各个方面,主要内容包含模块机制的揭示、异步I/O 实现原理的展现、异步编程的探讨、内存控制的介绍、二进制数据Buffer 的细节、Node 中的网络编程基础、Node 中的Web 开发、进程间的消息传递、Node 测试以及通过Node 构建产品需要的注意事项。最后的附录介绍了Node 的安装、调试、编码......一起来看看 《深入浅出Node.js》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具