[ Go高质量编程简介及性能调优 | 青训营笔记 ]
这是我参与「第五届青训营」伴学笔记创作活动的第 3 天
前言
本节主要简要介绍了高质量编程的定义和原则
一.本课重点
-
高质量编程
- 高质量编程简介
- 编码规范
- 性能优化建议
-
性能调优实战
- 性能调优简介
- 性能分析工具
- pprof实战
- 性能调优案例
二.详细内容
1.编码规范
代码格式
可以使用 gofmt 和 goimports 工具自动格式化代码。对于 GoLand,可以在 Settings - Tools - Actions on Save 中打开 Reformat code 和 Optimize imports(不出意外的话,它们应当是默认启用的)。也可通过 Ctrl+Alt+L 快捷键格式化代码(其实所有 Jetbrains 的 IDE 都支持使用这个快捷键格式化代码)。
注释
一个好的代码注释应当做到以下几点:
-
解释代码作用;
-
解释代码如何做的;
-
解释代码实现的原因;
-
解释代码什么情况会出错;
-
公共符号始终要注释(但是不需要注释实现接口的方法)。
2. 命名规范
变量
- 简洁胜于冗长;
- 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写(例如使用 ServerHTTP 而不是 ServerHttp,使用 XMLHTTPRequest 或是 xmlHTTPRequest 而不是 XmlHttpRequest);
- 变量距离其被使用的地方越远,则需要携带更多的上下文信息(尤其是全局变量)。
3.性能优化建议
简介:
- 性能优化的前提是满足正确可靠、简洁清晰等质量因素
- 性能优化是综合评估,有时候时间效率和空间效率可能对立,所谓时间换空间空间换时间
Benchmark
性能表现需要实际数量来衡量,Go语言提供了支持基准性能测试的benchmark工具
// 一个例子
// from fib.go
func Fib(n int) int {
if n < 2 {
return n
}
return Fib(n - 1) + Fib(n - 2)
}
// from fib_test.go
func BenchmarkFib10(b *testing.B) {
// run the Fib funciton b.N times
for n := 0; n < b.N; n++ {
Fib(10
}
}
复制代码
通过go test -bench=. -benchmen来进行测试
运行结果说明:
Slice预分配内存
尽可能在使用make()初始化切片的时候就提供容量信息,执行时间会差很多
究其原因是因为
- 切片本质是一个数组片段的描述包括数字指针、片段的长度以及片段的容量
- 切片操作并不复制切片指向的元素
- 创建一个新的切片会复用原来切片的底层数组
另一个陷阱:大内存未释放
有一种情况,原切片由大量元素构成,但是我们在原切片的基础上切片,虽然只使用了很小一段,但底层数组在内存中仍然占据了大量的空间,得不到释放。
这个时候我们可以用copy代替re-slice
Map预分配内存
与Slice相似地,如果初始化size也可以很大程度上优化性能,分析如下:
- 不断向map中添加元素会触发map的扩容
- 提前分配好空间可以减少内存拷贝和Rehash的消耗
strings.Builder
在字符串拼接的过程中,使用strings.Builder往往比直接+要快,分析如下:
- 字符串在Go语言中是不可变类型,占用内存大小是固定的
- 使用
+每次都会重新分配内存 strings.Builder, bytes.Buffer底层都是[]byte数组- 内存扩容策略,不需要每次拼接重新分配内存
// 一个strings.Builder例子
func StrBuilder(n int, str string) string {
var builder strings.Builder
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
复制代码
空结构体
使用空结构体节省内存,分析如下:
-
空结构体
struct{}实例不占据任何的内存空间 -
可作为各种场景下的占位符使用
- 节省资源
- 空结构体本身具备很强的语义,不需要任何值,仅作为占位符
// 一个例子
func EmptyStructMap(n int) {
m := make(map[int]struct{})
for i := 0; i < n; i++ {
m[i] = struct{}{}
}
}
func BoolMap(n int){
m := make(map[int]bool)
for i := 0; i < n; i++ {
m[i] = false
}
}
// 比较性能即可
三.实战例子
可以根据字节课程实验,对于小白难了
四.课程总结
了解了Go高质量编程简介及性能调优,守护很多。
五.参考文献
-
字节内部课:高质量编程与性能调优实战