生成代码中也做相应改造:
func (p *Demo) BLength() int { l := 0 l += bthrift.Binary.StructBeginLength("Demo") if p != nil { l += p.field1Length() l += p.field2Length() l += p.field3Length() ... } l += bthrift.Binary.FieldStopLength() l += bthrift.Binary.StructEndLength() return l}func (p *Demo) FastWrite(buf []byte) int { offset := 0 offset += bthrift.Binary.WriteStructBegin(buf[offset:], "Demo") if p != nil { offset += p.fastWriteField2(buf[offset:]) offset += p.fastWriteField4(buf[offset:]) offset += p.fastWriteField1(buf[offset:]) offset += p.fastWriteField3(buf[offset:]) } offset += bthrift.Binary.WriteFieldStop(buf[offset:]) offset += bthrift.Binary.WriteStructEnd(buf[offset:]) return offset}
使用 SIMD 优化 Thrift 编码公司内广泛使用 list<i64/i32> 类型来承载 ID 列表,并且 list<i64/i32> 的编码方式十分符合向量化的规律,于是我们用了 SIMD 来优化 list<i64/i32> 的编码过程 。
我们使用了 avx2,优化后的结果比较显著,在大数据量下针对 i64 可以提升 6 倍性能,针对 i32 可以提升 12 倍性能;在小数据量下提升更明显,针对 i64 可以提升 10 倍,针对 i32 可以提升 20 倍 。
减少函数调用inlineinline 是在编译期间将一个函数调用原地展开,替换成这个函数的实现,它可以减少函数调用的开销以提高程序的性能 。
在 Go 中并不是所有函数都能 inline,使用参数-gflags="-m"运行进程,可显示被 inline 的函数 。以下几种情况无法内联:
- 包含循环的函数;
- 包含以下内容的函数:闭包调用,select,for,defer,go 关键字创建的协程;
- 超过一定长度的函数,默认情况下当解析 AST 时,Go 申请了 80 个节点作为内联的预算 。每个节点都会消耗一个预算 。比如,a = a + 1 这行代码包含了 5 个节点:AS, NAME, ADD, NAME, LITERAL 。当一个函数的开销超过了这个预算,就无法内联 。
// The debug['l'] flag controls the aggressiveness. Note that main() swaps level 0 and 1, making 1 the default and -l disable. Additional levels (beyond -l) may be buggy and are not supported.// 0: disabled// 1: 80-nodes leaf functions, oneliners, panic, lazy typechecking (default)// 2: (unassigned)// 3: (unassigned)// 4: allow non-leaf functions
内联虽然可以减少函数调用的开销,但是也可能因为存在重复代码,从而导致 CPU 缓存命中率降低,所以并不能盲目追求过度的内联,需要结合 profile 结果来具体分析 。go test -gcflags='-m=2' -v -test.run TestNewCodec 2>&1 | grep "function too complex" | wc -l48go test -gcflags='-m=2 -l=4' -v -test.run TestNewCodec 2>&1 | grep "function too complex" | wc -l25
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字节跳动官方出品的免费图标库,超好用还能自定义修改
- API怎么选?比较SOAP,REST,GraphQL和RPC
- 为啥需要RPC,而不是简单的HTTP?
- Rhino 字节跳动全链路压测的实践
- 从RPC到服务化框架
- YARN 在字节跳动的优化与实践
- 胎心115
- 聊聊从RPC到服务治理框架
- 主流RPC框架通讯协议实现原理与源码解析
- SpringBoot中使用dubbo实现RPC调用