首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go 优化技巧

Go 优化技巧

原创
作者头像
Michel_Rolle
修改于 2024-07-08 10:21:50
修改于 2024-07-08 10:21:50
3.3K0
举报
文章被收录于专栏:golang分享golang分享

大概什么时候会想到优化

  • 某个函数会被频繁调用时
  • 接口或者是数据结构设计不算合理从而内存占用过高时
  • 接口响应耗时太多
  • 当代码太乱,问题频出

那发现问题的方式有哪些 ?

  • 单接口压测(这里一般是新接口或者是接口有改动时),固定QPS压测
  • 极限QPS压测(这种一般是来查看接口的最大承压规模)
  • 全链路压测(这一块儿主要是针对于一些流量高峰前的准备)

一些代码评测工具

Go代码评估工具:

  1. goreporter – 生成Go代码质量评估报告
  2. dingo-hunter – 用于在Go程序中找出deadlocks的静态分析器
  3. flen – 在Go程序包中获取函数长度信息
  4. go/ast – Package ast声明了关于Go程序包用于表示语法树的类型
  5. gocyclo – 在Go源代码中测算cyclomatic函数复杂性
  6. Go Meta Linter – 同时Go lint工具且工具的输出标准化
  7. go vet – 检测Go源代码并报告可疑的构造
  8. ineffassign – 在Go代码中检测无效赋值
  9. safesql – Golang静态分析工具,防止SQL注入

一些工具

  • benckmark
    1. 在对不同的工具、开源库等使用时,可以先对该方法进行benckmark。然后决定到底最后用哪一个
  • go pprof
    1. CPU Profile:用于诊断导致CPU占用较高的代码逻辑。
    2. Memory Profile:用于诊断导致内存占用较高的代码逻辑。
    3. Goroutine Profile:用于诊断导致Goroutine占用较高的代码逻辑,分析Goroutine执行的具体逻辑。
    4. Block Profile:用于诊断阻塞运行的代码逻辑,例如检测大锁(mutex锁定了一个运行时间较长的逻辑,并且有很多其他Goroutine在等待这个锁)

Go 内置的内存 profiler 可以让我们对线上系统进行内存使用采样,有四个相应的指标:

  1. inuse_objects:当我们认为内存中的驻留对象过多时,就会关注该指标
  2. inuse_space:当我们认为应用程序占据的 RSS 过大时,会关注该指标
  3. alloc_objects:当应用曾经发生过历史上的大量内存分配行为导致 CPU 或内存使用大幅上升时,可能关注该指标
  4. alloc_space:当应用历史上发生过内存使用大量上升时,会关注该指标

接下来会从这几方面来展开讲一下

Slice

  • 提前为slice分配内存

○ 在必要的时候,使用第三个参数: make([]T, 0, len)

○ 如果事先不知道确切的数量并且slice是临时的,可以设置得大一些,只要slice在运行时不会增长。

  • 不要忘记使用“copy”

○ 这点是需要在复制时尽可能不要使用 append,例如,在合并两个或多个slice时。

  • 不要留下未使用的slice

○ 如果需要从slice中切下一小块并仅使用它,其实主要部分也会保留下来。可以使用copy产生一个新的slice,而旧的对象让GC回收。

string

  • strings.Builder,bytes.Buffer相近
  • 优先使用 strings.Builder 而不是 +=

struct

  • 通过内存对齐来减小struct大小
    • 可以对齐struct(根据字段的大小,以正确的顺序排列),从而可以减小struct本身的大小
    • 遍历 []struct{} 使用下标而不是 range
    • 有的时候我们在使用channel的时候,通常如果是来表示一个标识,而不是发送数据的情况下,用于通知子协程来完成一些任务的情况,这种情况就比较好实用 空结构体了

defer

  • 尽量不要使用 defer,或者至少 不要在循环中使用defer 。

map

  • 跟Slice一样,需要提前分配内存
    • 初始化map时,指定它的大小
  • 如果需要表示占位时,其value用空结构体表示
    • struct{} 什么都不是
  • 清空map
    • map只能增长,不能缩小。需要控制这一点——完全而明确地重置map
  • 指针使用上
    • 如果 map 不包含指针,而且要知道字符串也是指针——使用[]byte而不是字符串作为键。

interface

  • 计算内存分配 ○ 请记住,要给一个接口赋值,首先需要将其拷贝到某处,然后粘贴一个指针。关键字是拷贝。事实证明,装箱和拆箱的成本将近似于结构体的大小和一次分配。

sync.Pool

fasthttp。它几乎把所有的对象都用sync.Pool维护,所以它才自称是http的10倍,但其实没

协程池

绝大部分应用场景,go是不需要协程池的。当然,协程池还是有一些自己的优势:

  1. 可以限制goroutine数量,避免无限制的增长。
  2. 减少栈扩容的次数。
  3. 频繁创建goroutine的场景下,资源复用,节省内存。(需要一定规模。一般场景下,效果不太明显。)

go对goroutine有一定的复用能力。所以要根据场景选择是否使用协程池,不恰当的场景不仅得不到收益,反而增加系统复杂性。

减小锁消耗

并发场景下,对临界区加锁比较常见。带来的性能隐患也必须重视。常见的优化手段有:

  • 减小锁粒度:go标准库当中,math.rand就有这么一处隐患。当我们直接使用rand库生成随机数时,实际上由全局的globalRand对象负责生成。globalRand加锁后生成随机数,会导致我们在高频使用随机数的场景下效率低下。
  • atomic:适当场景下,用原子操作代替互斥锁也是一种经典的lock-free技巧。标准库中sync.map针对读操作的优化消除了rwlock,是一个标准的案例。对它的介绍文章也比较多,不在赘述。

将多个小对象合并成一个大的对象

减少不必要的指针间接引用,多使用copy引用

例如使用bytes.Buffer代替*bytes.Buffer,因为使用指针时,会分配2个对象来完成引用。

cpu耗时优化

  1. make时提前预估size
  2. 临时的map、slice采用sync.pool
  3. 大于32k也可以用sync.pool
  4. 不滥用goroutine,减少gc压力
  5. 不滥用mutex,减少上下文切换
  6. []byte与string临时变量转换用unsafe
  7. 减少reflect、defer使用
  8. atomic无锁使用

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Go语言的编译优化技巧
编译优化是指在编译过程中,通过各种技术手段,提高生成代码的执行效率和资源利用效率。Go语言的编译器在编译过程中,会自动进行一些基本的优化,但通过合理的代码设计和编译参数设置,我们可以进一步提升程序的性能。
二一年冬末
2024/07/02
3940
深度解密Go语言之sync.pool
最近在工作中碰到了 GC 的问题:项目中大量重复地创建许多对象,造成 GC 的工作量巨大,CPU 频繁掉底。准备使用 sync.Pool 来缓存对象,减轻 GC 的消耗。为了用起来更顺畅,我特地研究了一番,形成此文。本文从使用到源码解析,循序渐进,一一道来。
梦醒人间
2020/04/27
1.3K0
Go 高性能编程技法
作者:dablelv,腾讯 IEGggG 后台开发工程师 代码的稳健、可读和高效是我们每一个 coder 的共同追求。本文将结合 Go 语言特性,为书写效率更高的代码,从常用数据结构、内存管理和并发,三个方面给出相关建议。话不多说,让我们一起学习 Go 高性能编程的技法吧。 常用数据结构 1.反射虽好,切莫贪杯 标准库 reflect 为 Go 语言提供了运行时动态获取对象的类型和值以及动态创建对象的能力。反射可以帮助抽象和简化代码,提高开发效率。 Go 语言标准库以及很多开源软件中都使用了 Go 语言的反
腾讯技术工程官方号
2022/03/18
2.1K0
PHP转Go速学手册
整理了一份简要的手册,帮助大家高效的上手Go语言,主要是通过对比PHP和Go的不同点来强化理解,内容主要分为以下四部分:
用户1093396
2021/07/28
2.5K0
Go 语言性能优化技巧
在软件开发中,性能往往是我们需要特别关注的方面之一。对于使用 Go 语言的开发者而言,如何编写高性能的代码是一个重要的考虑点。
南山竹
2024/07/09
1240
Go 语言性能优化技巧
《Go小技巧&易错点100例》第三十三篇
Go语言中广泛使用的validator库支持通过结构体标签定义校验规则。当内置规则无法满足需求时,我们可以轻松扩展自定义校验逻辑。
闫同学
2025/05/09
1220
《Go小技巧&易错点100例》第三十三篇
每个程序员都应该掌握的Golang性能优化秘技
Golang 作为一门“现代化”的语言,原生就包含了强大的性能分析工具 pprof 和 trace。pprof 工具常用于分析资源的使用情况,可以采集程序运行时的多种不同类型的数据(例如 CPU 占用、内存消耗和协程数量等),并对数据进行分析聚合生成的报告。trace 工具则关注程序运行时的事件(例如协程状态切换,GC 的开始和结束、系统调用等等),常用于分析延迟、阻塞和调度等问题。掌握了这两个工具就足以满足大部分 Golang 程序的性能分析需求。
腾讯云开发者
2024/05/22
2.2K0
每个程序员都应该掌握的Golang性能优化秘技
fasthttp是如何做到比net/http快十倍的
小许之前分享过标准库net/http的实现原理,不过有个fasthttp的库号称比net/http快十倍呢!
小许code
2024/03/09
1.6K0
fasthttp是如何做到比net/http快十倍的
go语言最全优化技巧总结,值得收藏!
导语 | 本文总结了在维护go基础库过程中,用到或者见到的一些性能优化技巧,现将一些理解梳理撰写成文,和大家探讨。 一、常规手段 (一)sync.Pool 临时对象池应该是对可读性影响最小且优化效果显著的手段。基本上,业内以高性能著称的开源库,都会使用到。 最典型的就是fasthttp(网址:https://github.com/valyala/fasthttp/)了,它几乎把所有的对象都用sync.Pool维护。 但这样的复用不一定全是合理的。比如在fasthttp中,传递上下文相关信息的Requ
腾讯云开发者
2021/08/24
8760
go面试题目收集
使用append向Slice追加元素时, 如果Slice空间不足, 将会触发Slice扩容, 扩容实际上重新一配一块更大的内存, 将原Slice数据拷贝进新Slice, 然后返回新Slice, 扩容后再将数据追加进去。 扩容容量的选择遵循以下规则:
twelvecoder
2021/12/24
7480
go面试题目收集
计算密集型服务 性能优化实战始末
worker 服务消费上游数据(工作日高峰期产出速度达近 200 MB/s,节假日高峰期可达 300MB/s 以上),进行中间处理后,写入多个下游。在实践中结合业务场景,基于快慢隔离的思想,以三个不同的 consumer group 消费同一 Topic,隔离三种数据处理链路。
薯条的编程修养
2022/08/10
9350
计算密集型服务 性能优化实战始末
Go面经
Wall clock(time) VS Monotonic clock(time)
公众号guangcity
2022/12/02
4751
Gitlab CI/CD 实践四:Golang 项目 CI/CD 流水线配置
gdb是linux系统自带的调试器,功能十分强大,它不仅支持C/C++调试,也支持GO程序调试。 支持打断点,查看变量值,查看调用堆栈。使用前需要在编译时禁用编译器优化、内联优化,这样看到的代码才和源代码一致。
Yuyy
2024/07/14
4620
go pprof实战
1 为什么要进行性能优化 1.1 哪些情况需要进行性能优化 其实关于性能优化的主题,网上已经讨论很多次,这里谈一下我的理解,那么其实核心就是2个点: 服务一直高负载,业务增长需要经常扩容 架构不能满足业务发展,需要重构,与此同时需要进行服务的压测&性能优化 1.2 性能优化的一般步骤 准备阶段:发现系统性能问题,明确优化方向 分析阶段:通过各种工具和手段,初步定位瓶颈点 调优阶段:根据定位到的瓶颈点,进行性能调优 测试阶段:实际验证调优效果,如果不能满足期望要求,那么可能需要重复2-3步骤(如果还不行可能
QQ音乐技术团队
2021/05/14
1.9K0
Go 应用优化指北
这是一个速度决定一切的时代,我们的生活在不断地数字化,线下的流程依然在持续向线上转移,转移过程中,作为工程师,我们会碰到各种各样的性能问题。
KevinYan
2021/08/06
3560
Go 应用优化指北
Go语言核心技术深度剖析与高并发实战
#mermaid-svg-k8ekEdaHWMx03TZF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-k8ekEdaHWMx03TZF .error-icon{fill:#552222;}#mermaid-svg-k8ekEdaHWMx03TZF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-k8ekEdaHWMx03TZF .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-k8ekEdaHWMx03TZF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-k8ekEdaHWMx03TZF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-k8ekEdaHWMx03TZF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-k8ekEdaHWMx03TZF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-k8ekEdaHWMx03TZF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-k8ekEdaHWMx03TZF .marker.cross{stroke:#333333;}#mermaid-svg-k8ekEdaHWMx03TZF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-k8ekEdaHWMx03TZF .pieCircle{stroke:black;stroke-width:2px;opacity:0.7;}#mermaid-svg-k8ekEdaHWMx03TZF .pieTitleText{text-anchor:middle;font-size:25px;fill:black;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-k8ekEdaHWMx03TZF .slice{font-family:"trebuchet ms",verdana,arial,sans-serif;fill:#333;font-size:17px;}#mermaid-svg-k8ekEdaHWMx03TZF .legend text{fill:black;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:17px;}#mermaid-svg-k8ekEdaHWMx03TZF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
大熊计算机
2025/07/15
1370
Go语言核心技术深度剖析与高并发实战
day3 | 高质量编程与性能调优实战 | 第三届字节跳动青训营笔记
实际应用场景千变万化,各种语言的特性和语法各不相同。但是高质量编程遵循的原则是相通的
千羽
2022/05/31
6980
day3 | 高质量编程与性能调优实战 | 第三届字节跳动青训营笔记
Go语言高性能编程手册(王权富贵)
代码的稳健、可读和高效是我们每一个 coder 的共同追求。本文将结合 Go 语言特性,为书写效率更高的代码,从常用数据结构、内存管理和并发,三个方面给出相关建议。话不多说,让我们一起学习 Go 高性能编程的技法吧。
曾高飞
2025/06/16
1120
白话 Golang 协程池
并发指在一段时间内有多个任务(程序,线程,协程等)被同时执行。注意,不是同一时刻。
恋喵大鲤鱼
2021/05/18
2K0
白话 Golang 协程池
基础总结 (Go篇)
注: 此系列内容来自网络,未能查到原作者。感觉不错,在此分享。不排除有错误,可留言指正。
fliter
2023/06/18
5260
基础总结 (Go篇)
相关推荐
Go语言的编译优化技巧
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档