Dolt,一个基于Go语言的SQL数据库,一个看似无操作的重构导致sysbench性能下降了30%,这是由于意外的堆分配引起的。问题源于`nodeStore`类型的一个`ReadBytes`方法使用了值接收器而不是指针接收器。这导致每次调用期间在堆上不必要地创建了`nodeStore`的副本,这是由编译器无法证明接收器值不会逃逸函数引起的。
Go的逃逸分析确定变量是否可以在栈上分配,或者必须放在堆上。如果编译器不能保证变量不会超出当前栈帧的生命周期,它默认为堆分配,这由于分配和垃圾回收开销而更慢。
通过切换到指针接收器,避免了不必要的复制,消除了堆分配并恢复了性能。这段经历突出了理解Go内存分配行为以及使用像`go build -gcflags "-m"`这样的工具来分析编译器决策以进行性能优化的重要性。