第三节高质量编程与性能调优实战 | 青训营笔记

148 阅读6分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记

讲师和内容介绍

image.png image.png

  • 介绍编码规范,帮助大家写出高质量程序
  • 介绍 Go 语言的性能优化建议,分析对比不同方式对性能的影响和背后的原理
  • 讲解常用性能分析工具 pprof 的使用和工作原理,熟悉排查程序性能问题的基本流程
  • 分析性能调优实际案例,介绍实际性能调优时的工作内容

课程目录

image.png

高质量编程

image.png 注意边界和异常情况 image.png

编码规范

image.png image.png 代码格式使用gofmt自动化格式 image.png image.png image.png image.png image.png image.png 不需要注释接口方法 image.png image.png 表达上下文信息?有点类似写论文? image.png 命名:简洁胜于冗长,缩略词大写,开头不需要导出要小写 全局变量的名字多带上下文信息,了解变量的含义 image.png image.png image.png 函数名尽量简短,注意返回类型相同否 image.png 1更好,应为包相同可以省略,用的时候是http.Serve image.png image.png image.png 都有return,避免分支嵌套 image.png image.png 对于异常情况,正常返回 image.png image.png 只出现一次错误,直接errors.NeW image.png image.png 错误链是否有指定的错误 image.png image.png image.png 一般不用panic,示例代码启动一个消费队列的消费组,启动失败会用log.panicf方法,最后就会打印错误日志,发送panic(需要尽早暴露问题) image.png 其他库碰到panic怎么做,影响自身逻辑的时候,需要用recover以,
关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的),golang中的recover也只是发生宕机之后的后事处理 image.png recover的操作在于出现panic的上下文记录,主要就是打印调用栈记录下来,能够知道什么原因导致的 image.png image.png 从左往右,1 2 image.png 3 1

性能优化

image.png image.png go test -bench=. -benchmem image.png 8 是设置的核数 image.png 有无预分配消息,如果提前分配会有好的效果 image.png image.png 创建一个新的数组,用copy和直接retrun的区别 go test -run=. -v image.png map有点同理 image.png image.png 字符串是高频操作 image.png 直接用+会变差,原因会开辟新空间 image.png image.png 知道最后长度的时候,可以进一步提高效率,用grow的方法直接把大小计算好 image.png 可以看最后一列内存分配的次数 image.png image.png 使用set的情况下,只要键,不用值 image.png 多线程计数器,atimic维护变量,可以看出用atomic的时间性能比较好 image.png image.png

性能调优实战

image.png image.png

性能分析工具pprof

image.png image.png image.png go mod tidy go mod init github.com/wolfogre/go-pprof-practice main方法流程:把pprof注册到httpserver,设置了cpu数,开启了锁和阻塞的调用跟踪,实际启动时6060 image.png 访问http://127.0.0.1:6060/debug/pprof/ 根据参考分析哪些点存在性能问题 image.png 点full 会是平铺的 image.png go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 采集十秒的数据来辅助性能问题 image.png image.png 使用了top指令的内容 image.png cum是调用其他函数的总耗时,没有调用的时候flat ==cum,flat都是调用别人的时候 flat == 0 image.png list eat image.png web命令可视化 go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/cpu" image.png 如果把重要的东西注释即可 image.png 如果i想要可视化,在指令里加 -http=:8080即可 image.png go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" image.png 可以发现mouse是占用最多,view是有很多,展示图要有graphviz image.png source视图类似list命令到的视图,代码注释后会发现内存下降 image.png 可以看到不同占用内存大小的问题 image.png image.png goroutine 协程的问题 image.png go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine" image.png 关心的协程的性能的问题可以知道有东西创造了很多协程 image.png image.png image.png go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex" image.png go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block" image.png 看到了block的的问题 image.png 回到命令行问题,有没有特殊的问题,丢弃了四个节点,用了简单过滤条件,可以展示出来 image.png 找到了阻塞操作 image.png image.png 1652259041.png image.png image.png image.png main里有个block,rate image.png image.png 需要优化的案例 image.png image.png image.png image.png image.png 紫色的点可以定位,可以看到每次拿到之后就要解析,这里面没用到缓存机制,只要修改变动的时候再去修改即可 image.png 规范日志 image.png 对于高峰和低峰进行采样,专门优化即可,监控上报不需要实时,直接异步上报即可 image.png 对于功能方面需要进行修改,对比实例,需要对字段进行改动 image.png image.png 单独一点的优化转变到链路的优化 image.png 通过火焰图来判断,百分比来改善 image.png image.png

Q&A

1:关于编码规范,本包调用的时候?
和之前可以一样,没有必要修改,你知道自己写的方法了
2:抖音项目地址是否支持https地址 可以直接配置域名和服务地址,后面具体更新在文档里
3:go的设计模式?
设计模式为了写出更好的代码,go本身自己的实践经验参考一些手册,和java区别很大
4:设计项目的过程是否支持自定义?
项目的话是服务端的青训营,自定义功能对于客户端也得有调整,就没有办法统一评估了,暂时不会开发客户端修改的调整,专注于服务端的性能,和用户使用场景 5:线上应用panic排除,除了打标还有什么方式?
用到panic的话,会有日志能够定位问题,panic调用堆栈,可以查看代码逻辑,对于nil的情况是不是传入参数导致后续调用panic了,进而一步一步定义问题
go本身自带debug工具对于线上服务不太好开放,怕对服务产生影响
如果产生很难的问题,会拿出实例单独对go本身的debug方式,打断点来看内存分配和堆栈 6:压力测试怎么做的?
好的压测平台公司是有单独团队,对于个人需要了解一下上述提到的工具,实现自己功能的时候可以对自己小块的逻辑是怎么样的?也有一些开源的压力测试工具产生报告?先对这些压力测试碰到的问题进行了解,后续真的需要用到的话会更熟悉一些
7:接口规范? 实际关于其他类型,可以观看手册里的相关类型的文档。