Go 1.22 - 更加强大的 Go 执行跟踪

在这里插入图片描述

原文:Michael Knyszek - 2024.03.14

runtime/trace 包含了一款强大的工具,用于理解和排查 Go 程序。这个功能可以生成一段时间内每个 goroutine 的执行追踪。然后,你可以使用 go tool trace 命令(或者优秀的开源工具 gotraceui)来可视化和探索这些追踪数据。

追踪的魔力在于,它可以轻易地揭示出程序中那些难以通过其他方式看到的信息。例如,一个并发瓶颈可能是很多 goroutine 在同一个 channel 上阻塞,这在 CPU profile 中可能很难被看到,因为没有执行样本可以采样。但在执行追踪中,执行的缺失或不足 将以惊人的清晰度展现出来,被阻塞的 goroutine 的堆栈追踪将迅速指向问题根源。

在这里插入图片描述

Go 开发者甚至能够使用 任务、区域 和 日志 来对自己的程序进行插桩,以便将更高的关注点与底层执行细节进行关联。

问题

不幸的是,执行追踪中的丰富信息往往无法触及。历史上,四个主要问题阻碍了追踪的使用。

  • 追踪的开销很大。
  • 追踪的扩展性不强,可能会变得过大而无法分析。
  • 往往不清楚何时开始追踪以捕获特定的不良行为。
  • 鉴于缺乏用于解析和解释执行追踪的公共包,只有最具冒险精神的 gopher 才能编程分析追踪。

如果你在过去几年中使用过追踪,可能已经被这些问题中的一个或多个所困扰。但我们很高兴地分享,在过去的两个 Go 版本中,我们在这四个领域都取得了大的进步。

低开销的追踪

在 Go 1.21 之前,许多应用的追踪运行时开销大约在 10-20% 的 CPU 之间,这限制了追踪的使用情况,不能像 CPU profiling 那样持续使用。事实证明,追踪的大部分成本都归结于 traceback。运行时产生的许多事件都附带有堆栈追踪,这些对于实际识别 goroutine 在关键执行时刻的行为是非常有价值的。

感谢 Felix Geisendörfer 和 Nick Ripley 在优化 traceback 效率方面的工作,执行追踪的运行时 CPU 开销已经大幅降低,对于许多应用来说,现在只有 1-2%。你可以在 Felix 的精彩博客文章中关于这项工作的内容。

可扩展的追踪

追踪格式及其事件的设计主要考虑到了相对高效的数据生成和输出(emission),但需要工具来解析和保留整个追踪的状态。几百 MiB 的追踪可能需要几 GiB 的 RAM 来分析!

不幸的是,这个问题对于跟踪的生成方式至关重要。为了保持运行时开销低,所有事件都被写入等同于线程局部缓冲区的地方。但这意味着事件出现的顺序并非其真实顺序,追踪工具需要负责弄清楚究竟发生了什么。

使追踪在保持开销低的同时具有可扩展性的关键是,不定期地切分正在生成的追踪。每个切分点都会表现得有点像同时禁用和重新启用追踪。到目前为止的所有追踪数据都会代表一个完整且自包含的追踪,而新的追踪数据将无缝地接续前者。

你可能想象到,修复这个问题需要在运行时重新思考和重写追踪实现的很多基础部分。我们很高兴地说,这项工作在 Go 1.22 中完成,并且现在已经普遍可用。许多很好的改进随着重写一起出现,包括对 go tool trace 命令的一些改进。如果你感到好奇,所有的细节都在设计文档中。

(注意:go tool trace 仍然将完整的追踪加载到内存中,但现在已经可以移除这个限制,用于 Go 1.22+ 程序生成的追踪。)

Flight recording

假设你正在开发一个网络服务,一个 RPC 花费了很长时间。你不能在已经知道 RPC 花费了一段时间的点开始追踪,因为慢请求的根本原因已经发生并且没有被记录下来。

有一种可以帮助解决这个问题的技术,叫做 Flight recording,你可能已经在其他编程环境中熟悉了。Flight recording 的关键理念是,持续进行追踪,并始终保留最新的追踪数据,以便随时使用。然后,一旦发生了有趣的事情,程序就可以直接写出它所拥有的所有内容!

在追踪可以被切分之前,这基本上是无法实现的。但是,由于开销较低,连续跟踪现在是可行的,以及运行时现在可以在需要的时候随时切分追踪,结果,实现 Flight recording 非常简单。

因此,我们很高兴宣布一个 Flight recorder 实验特性,可在 golang.org/x/exp/trace 包中找到。

请试试看!下面是一个示例,设置了 Flight recorder 以捕获长时间的 HTTP 请求,以帮助你入门。

// 设置 Flight recorder 。
fr := trace.NewFlightRecorder()
fr.Start()// 设置并运行一个 HTTP 服务器。
var once sync.Once
http.HandleFunc("/my-endpoint", func(w http.ResponseWriter, r *http.Request) {start := time.Now()// 做一些事情...doWork(w, r)// 我们看到了一个长请求。拍摄一张快照!if time.Since(start) > 300*time.Millisecond {// 为了简单起见,只做一次,但你可以拍摄多于一张的快照。once.Do(func() {// 抓取快照。var b bytes.Buffer_, err = fr.WriteTo(&b)if err != nil {log.Print(err)return}// 将它写入一个文件。if err := os.WriteFile("trace.out", b.Bytes(), 0o755); err != nil {log.Print(err)return}})}
})
log.Fatal(http.ListenAndServe(":8080", nil))

如果你有任何反馈,无论是积极的还是消极的,都请分享到 proposal issue 中!

追踪 reader API

伴随着追踪实现的重写,我们也努力清理了其他的追踪内部工具,如 go tool trace。这促使我们尝试创建一个足够优秀,以至于可以分享的追踪 reader API,这个 API 能够让追踪数据更易于访问。

就像 Flight recorder 一样,我们很高兴宣布我们也有一个实验性的追踪 reader API,我们希望分享出来。它在与 Flight recorder 相同的包 golang.org/x/exp/trace 中可用。

我们认为它足够好以开始在其之上构建东西,所以请试试看!下面是一个示例,它测量了阻塞等待网络的 goroutine 阻塞事件的比例。

// 从 STDIN 开始读取。
r, err := trace.NewReader(os.Stdin)
if err != nil {log.Fatal(err)
}var blocked int
var blockedOnNetwork int
for {// 读取事件。ev, err := r.ReadEvent()if err == io.EOF {break} else if err != nil {log.Fatal(err)}// 处理事件。if ev.Kind() == trace.EventStateTransition {st := ev.StateTransition()if st.Resource.Kind == trace.ResourceGoroutine {id := st.Resource.Goroutine()from, to := st.GoroutineTransition()// 寻找阻塞的 goroutines,并计数。if from.Executing() && to == trace.GoWaiting {blocked++if strings.Contains(st.Reason, "network") {blockedOnNetwork++}}}}
}
// 打印我们找到的内容。
p := 100 * float64(blockedOnNetwork) / float64(blocked)
fmt.Printf("%2.3f%% instances of goroutines blocking were to block on the network\n", p)

就像 Flight recorder 一样,proposal issue 将是留下反馈的好地方!

我们要特别提一下 Dominik Honnef,他是早期的试用者,提供了很好的反馈,并且对 API 的旧版追踪提供了支持。

感谢你们!

这项工作在很大程度上得益于诊断工作组的帮助,这个工作组是一年多前由来自 Go 社区的各个利益相关者共同发起的,并向公众开放的。

我们想花一点时间感谢那些,在过去一年中经常参加诊断会议的社区成员:Felix Geisendörfer, Nick Ripley, Rhys Hiltner, Dominik Honnef, Bryan Boreham, thepudds。

你们所有人的讨论、反馈和投入的工作,对我们取得今天的成就发挥了重要作用,谢谢你们!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757318.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud 整合 GateWay

目录 第一章 微服务架构图 第二章 Spring Cloud整合Nacos集群 第三章 Spring Cloud GateWay 第四章 Spring Cloud Alibaba 整合Sentinel 第五章 Spring Cloud Alibaba 整合SkyWalking链路跟踪 第六章 Spring Cloud Alibaba 整合Seata分布式事务 第七章 Spring Cloud 集成Auth用…

[Qt学习笔记]Release后的exe程序在新的电脑上出现“找不到MSVCP140.dll”的错误

1、背景介绍 我们在打包程序的时候一般都会把相关依赖库整体打包,这样程序在新的电脑和环境下就不需要再去配置对应的环境,但是有时候新程序在一台新的电脑运行时会出现“找不到MSVCP140.dll”这种错误,其原因就是在新电脑的操作系统中缺少一…

倒计时 7 天 | 立即加入 GDE 成长计划,飞跃成为谷歌开发者专家

谷歌开发者专家 (Google Developer Experts,GDE),又称谷歌开发者专家项目,是由一群经验丰富的技术专家、具有社交影响力的开发者和思想领袖组成的全球性社区。通过在各项活动演讲以及各个平台上发布优质内容来积极助力开发者、企业和技术社区…

AI助手 - 月之暗面 Kimi.ai

前言 这是 AI工具专栏 下的第四篇,这一篇所介绍的AI,也许是截至今天(204-03-19)国内可访问的实用性最强的一款。 今年年初,一直看到有人推荐 Kimi,不过面对雨后春笋般的各类品质的AI,说实话也有…

windows 多网卡情况dns解析超时问题的排查

最近遇到一个问题 多网卡,多网络环境下,dns解析总是超时。 排查之后发现是dns配置的问题,一个有线网络配置的内网dns,一个无线网络配置的公网dns 访问公网时莫名的时不时出现超时现象 初步排查是dns解析的耗时太长,…

【Go语言】Go语言中的函数

Go语言中的函数 Go语言中,函数主要有三种类型: 普通函数 匿名函数(闭包) 类方法 1 函数定义 Go语言函数的基本组成包括:关键字func、函数名、参数列表、返回值、函数体和返回语句。Go语言是强类型语言&#xff0…

【MySQL | 第五篇】MySQL事务总结

文章目录 5.MySQL事务5.1什么是事务?5.2什么是数据库事务?5.3数据库事务四大特性5.4并发事务带来的问题及解决方案?5.4.1脏读/不可重复读/幻读5.4.2不可重复读和幻读有什么区别?5.4.3解决并发事务带来的问题(1&#xf…

springboot实战笔记

springboot实战笔记 用户模块开发用户登录接口实现根据token获取用户信息检查账号是否可用用户注册接口实现 首页模块开发查询首页分类分页查询首页头条信息查询头条详情 头条模块开发登陆检查头条发布和登录保护拦截器头条根据id回显头条修改头条删除 用户模块开发 用户登录接…

聚观早报 | 阅文去年净利增三成;iQOO Z9系列官宣

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月20日消息 阅文去年净利增三成 iQOO Z9系列官宣 英伟达发布全新构架 一加Ace 3V设计细节 小米Civi 4 Pro核心…

章鱼网络 Community Call #19|​开启与 Eigenlayer 的合作

香港时间2024年3月8日12点,章鱼网络举行第19期 Community Call。 在过去的一个月,章鱼网络在成功完成 $NEAR Restaking 功能的安全审计之后,一直在稳步吸引关注。事实上,在整个行业中,我们是极少数已经推出 Restaking …

八大元素,让你的网站科技感拉满,极易落地执行。

Hello,我是大千UI工场,这篇分享各类网页UI的设计风格,就从大家最喜欢的科技感开始吧,欢迎友友们持续关注,我将持续更新,如有设计需求,可以私信我。 在网页UI中,科技感是指通过设计元…

医学YOLOv8 | 脑肿瘤检测实战

在医疗保健领域,准确和高效地识别脑肿瘤是一个重大挑战。本文中,我们将探讨一种使用 YOLOv8,一种先进的目标检测模型,将脑肿瘤进行分类的新方法,其准确率达到了 99%。通过将深度学习与医学图像相结合,我们希…

【Android】【Bluetooth Stack】蓝牙电话本协议分析(超详细)

1. 精讲蓝牙协议栈(Bluetooth Stack):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅,【蓝牙协议栈】专栏会持续更新中.....敬请期待! 目录 1. 协议简述 1.1 PBAP…

个人商城系统开源(配置支付宝支付2)

原文地址:个人商城系统开源(配置支付宝支付2) - Pleasure的博客 下面是正文内容: 前言 在上一篇文章中我曾提到过关于网站支付宝支付的方法,接下来我们来介绍第二种。 个人博客地址:个人商城系统开源&…

GPT模型支持下的Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例应用

随着航空、航天、近地空间等多个遥感平台的不断发展,近年来遥感技术突飞猛进。由此,遥感数据的空间、时间、光谱分辨率不断提高,数据量也大幅增长,使其越来越具有大数据特征。对于相关研究而言,遥感大数据的出现为其提…

FPGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发+GTX 8b/10b编解码SFP光口传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博主所有FPGA工程项目-->汇总目录本博已有的 SDI 编解码方案本方案的SDI接收发送本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI…

C++:类和对象(上篇)

目录: 一:面向对象和过程的介绍 二:类的引入 三:类的定义 四:类的访问限定符以及封装 五:类的作用域 六:类的实例化 七:类对象大小的计算 八:类成员函数的this指…

【Linux】编译器-gcc/g++的使用(预处理、编译、汇编、连接)

目录 01.预处理(宏替换) 02.编译(生成汇编) 03.汇编(生成机器可识别码) 04.连接(生成可执行文件或库文件) 05.选项 编译器在编译代码时包含以下四个步骤:1.预处理 2…

MongoDB启动报错

spring boot 引入MongoDB启动报错 java.lang.IllegalStateException: Failed to introspect Class [io.micrometer.core.instrument.binder.mongodb.DefaultMongoConnectionPoolTagsProvider] from ClassLoader [sun.misc.Launcher$AppClassLoader18b4aac2] at org.springfra…

爬虫综合案例-获取房源信息并在地图上显示

文章目录 1.项目介绍2.项目分析3.爬取房源信息4. 导入高德地图5.地图上显示房源信息6.运行程序 1.项目介绍 本次案例将从 58 同城信息网爬取相关城市的房源出租信息,然后通过高德地图把房源信息地图显示,通过地图进行浏览,点击相应的热点文字…