「2」Golang 工程化
这是我参与「第三届青训营 -后端场」笔记创作活动的的第二篇笔记。
创建时间: May 16, 2022 4:43 PM
「5.7」青训营 Golang 工程化课程,笔记整理。
测试 - 工程化
💡 早些时候用过 testing.T 在算法课设上,用它来简单做一些测试。所以课后只实践了 testing.Benchmark 和 Mock 部分。
GoBenchmark
-
定义
type Server int var ( Servers [10]Server ) func init() { InitServers() } func InitServers() { for i, _ := range Servers { Servers[i] = Server(i + maxIdx) } } func Select() Server { return Servers[rand.Intn(len(Servers))] } func FastSelect() Server { return Servers[fastrand.Intn(len(Servers))] } -
测试
// init 取代 b.ResetTimer() func BenchmarkSelect(b *testing.B) { for i := 0; i < b.N; i++ { Select() } } func BenchmarkSelectParallel(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { Select() } }) } func BenchmarkFastSelect(b *testing.B) { for i := 0; i < b.N; i++ { FastSelect() } } func BenchmarkFastSelectParallel(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { FastSelect() } }) }
这里的记录中的代码和老师课上的稍有调整,我用 func init() 代替了 b.ResetTimer() 在我的理解中这样的修改应该是等价于重置时间的。
- 本机运行结果
BenchmarkXX-8 对应 GOMAXPROCS 核心数
cpu: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
BenchmarkSelect
BenchmarkSelect-8 63568075 20.85 ns/op
BenchmarkSelectParallel
BenchmarkSelectParallel-8 9219620 124.1 ns/op
BenchmarkFastSelect
BenchmarkFastSelect-8 165717588 6.649 ns/op
BenchmarkFastSelectParallel
BenchmarkFastSelectParallel-8 673691774 2.093 ns/op
对比结果,发现fastrand 性能应该优于 rand 的,并且并发场景下两者差距非常明显接近 60x。
课后注意到 PPT 中的留言提到 rand.Intn() 出现并发情况下性能骤降的原因是 rand 实现中维护了一把锁
简单找了一下源码
type lockedSource struct {
lk sync.Mutex
src *rngSource
}
// line: 387
func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
发现 rand 每次请求随机数都会操作这把资源锁,在并发场景下确实会带来性能瓶颈。
Mock 测试
Mock 曾经完全没接触过,用下来感觉是非常 Hack 的玩法。
monkey.Patch 可以插桩修改一个函数调用的返回结果。
Lab time
-
支持发布帖子
-
本地 ID 生成需要保证不重复、唯一性
-
雪花算法
- 前xxx位记录时间戳,后几位分配为id
- 序列号对应的时间戳会被保存,每次读取时间戳,如果时间戳相同,对序列号原子操作加一,组合成 uuid。
-
-
Append 文件,更新索引,注意 Map 的并发安全问题
- 分片加锁 map