今天,通过一个例子,一方面熟悉trace在自定义范围内的分析,另一方面golang 在协程调度策略上的浅析。

Show Code

// trace_example.go
package main import (
"context"
"fmt"
"os"
"runtime"
"runtime/trace"
"sync"
) func main(){
// 为了看协程抢占,这里设置了一个cpu 跑
runtime.GOMAXPROCS(1) f, _ := os.Create("trace.dat")
defer f.Close() _ = trace.Start(f)
defer trace.Stop() ctx, task := trace.NewTask(context.Background(), "sumTask")
defer task.End() var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i ++ {
// 启动10个协程,只是做一个累加运算
go func(region string) {
defer wg.Done() // 标记region
trace.WithRegion(ctx, region, func() {
var sum, k int64
for ; k < 1000000000; k ++ {
sum += k
}
fmt.Println(region, sum)
})
}(fmt.Sprintf("region_%02d", i))
}
wg.Wait()
}

首先,代码的功能非常简单,只是启动10个协程,每个协程处理的工作都是一样的,即把0 ... 1000000000 做了sum 运算。

其次,代码中,添加了Task 和 Task 的Region,是我们更好的发现我们协程的位置(当然,我这里都捕获了,只是用Region 做了标识),并将记录的 trace 数据写入trace.dat 文件中。

最后,为了更好的看到协程对cpu的抢占,所以把cpu的个数限制为1个。

编译并运行,会得到如下结果:

# go build trace_example.go
# ./trace_example
region_09 499999999500000000
region_00 499999999500000000
region_01 499999999500000000
region_02 499999999500000000
region_03 499999999500000000
region_04 499999999500000000
region_05 499999999500000000
region_06 499999999500000000
region_07 499999999500000000
region_08 499999999500000000

从结果中,我们可以看出,协程执行的顺序不是那么有序。但是真实是怎么执行的呢?我们从 trace.dat 中获取答案。

Trace 分析

执行下面命令,打开trace 的web服务:

# go tool trace trace.dat
2020/04/16 17:34:09 Parsing trace...
2020/04/16 17:34:10 Splitting trace...
2020/04/16 17:34:10 Opening browser. Trace viewer is listening on http://127.0.0.1:53426

我们先从分析整个协程入手, 从这里可以看出,我们的协程其实没有按照时间片轮询的方式跑(毕竟这是一个纯计算性的工作)

而从Task中,我们观察所有自定义的Region 和goroutine.

从图中可以看出,task 任务所关注的region 是一个一个跑的,region_09 先执行了,这个也从我们的输出中得到了验证。从图中也可以看到,我们的goroutineid(G1, G10, G12 等, 虽然我们在go编写代码时并不能拿到这个goroutineid).

总结与反思

除了实操了一次 task 和 region 的自定义做trace 分析外,我们还能从这个例子中找到些什么信息。

  1. goroutine 肯定是存在的
  2. goroutine 的启动肯定不是有序的, 这一点从task 的图中就可以明显看出来
  3. goroutine 如果没有阻塞的服务的话,会一直占用cpu的(所以有了 runtime.Gosched() 的存在)

所以,对于一些占用高频cpu的服务(比如说加解密,编解码服务等)如果有别的优先级比较高的goroutine在工作,可以适当的让出CPU, 保证服务正常有序工作。

golang trace 分析 简例的更多相关文章

  1. Form_通过Trace分析Concurrent和Form性能和异常详解(案例)

    2014-06-21 Created By BaoXinjian

  2. linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到client的连接后,发送数据给client:clie ...

  3. 5.3linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在Linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后 ...

  4. RabbitMQ消息可靠性分析 - 简书

    原文:RabbitMQ消息可靠性分析 - 简书 有很多人问过我这么一类问题:RabbitMQ如何确保消息可靠?很多时候,笔者的回答都是:说来话长的事情何来长话短说.的确,要确保消息可靠不只是单单几句就 ...

  5. Golang逃逸分析

    Golang逃逸分析 介绍逃逸分析的概念,go怎么开启逃逸分析的log. 以下资料来自互联网,有错误之处,请一定告之. sheepbao 2017.06.10 什么是逃逸分析 wiki上的定义 In ...

  6. 【MySQL 原理分析】之 Trace 分析 order by 的索引原理

    一.背景 昨天早上,交流群有一位同学提出了一个问题.看下图: 我不是大佬,而且当时我自己的想法也只是猜测,所以并没有回复那位同学,只是接下来自己做了一个测试验证一下. 他只简单了说了一句话,就是同样的 ...

  7. EBS trace分析

    下载Trace Analyzer,打开bin下的traceanalyzer.bat 即可分析EBS的trace文件,图形化界面,无需tkprof 需要配置javahome,确认java版本为1.6以上 ...

  8. PLSQL_性能优化效能跟踪工具SQL Trace分析(案例)

    2014-06-25 Created By BaoXinjian

  9. Hibernate内存溢出分析一例

    公司业务系统在进行压力测试时,压测24小时后系统发生内存溢出.经过分析读dump文件,发现org.hibernate.stat.StatisticsImpl类的hashmap类型的变量存储了大量数据( ...

随机推荐

  1. vue后台管理系统权限处理

    vue后台管理系统权限 1.权限问题:用户和管理员进入管理系统看到的模块是不一样的,管理员看的的要比用户看到的多.需要用到动态加载路由,router.addRouters()来动态的挂载路由 // 1 ...

  2. 4. selenium中鼠标和键盘操作

    一.鼠标操作 第一步:引入模块函数 from selenium.webdriver.common.action_chains import ActionChains 第二步:元素定位 element ...

  3. Selenium系列(四) - 鼠标、键盘操作详细解读

    如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...

  4. hdu2112 dijkstra

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2112/ 只要需处理一下字符串,给他个编号再跑一半dijkstra就行. 代码如下: #include<bi ...

  5. 【HDU5934】Bomb——有向图强连通分量+重建图

    题目大意 二维平面上有 n 个爆炸桶,i−thi-thi−th爆炸桶位置为 (xi,yi)(x_i, y_i)(xi​,yi​) 爆炸范围为 rir_iri​ ,且需要 cic_ici​ 的价格引爆, ...

  6. TensorFlow RNN 教程和代码

    分析: 看 TensorFlow 也有一段时间了,准备按照 GitHub 上的教程,敲出来,顺便整理一下思路. RNN部分 定义参数,包括数据相关,训练相关. 定义模型,损失函数,优化函数. 训练,准 ...

  7. iOS isa 和 Class

    一.Runtime 简介 Runtime 又叫运行时,是一套底层的 C 语言 API,是 iOS 系统的核心之一.开发者在编码过程中,可以给任意一个对象发送消息,在编译阶段只是确定了要向接收者发送这条 ...

  8. 1.用eclipse创建maven工程

    第一步.File→New→Maven Project (需要下载安装配置Maven等,这些步骤省略) (找不到的话选Other,里面的Maven文件夹里有) 二.记得勾选上,然后点Next 三.填完点 ...

  9. java模拟栈的操作

    栈是一种有序列表,可以使用数组的结构来储存栈的数据内容 思路 1. 创建一个栈类StackArray 2. 定义一个top来模拟栈顶,初始化为-1 3. 入栈: 当有数据加入到栈的时候 top++ s ...

  10. linux中的文件类型、时间戳、文件管理

    一.linux 文件类型 1.普通文件:- ,f 2.目录文件:d 3.链接文件(符号链接):l 4.设备文件 字符设备(线性设备):c 块设备(非线性设备):b 5.命名设备:p 6.套接字文件:s ...