2022-08-05 (金)
明日から,15日まで休みにしたので10連休.
Go1.19でGenericsのパフォーマンス改善されたみたいだし,そろそろ色々なものをGenerics使った実装に置き換えてたのだけど,なんだかとても実行が遅い...
気になったのでコンパイル結果を眺めてみたけど,
type SimpleComparator[T comparable] struct{} func (c SimpleComparator[T]) Equal(a, b T) bool { return a == b } func main() { var c SimpleComparator[int] fmt.Println(c.Equal(42, 42)) }
こういう単純な例でも,インライン化されていない.
type IntComparator struct{} func (c IntComparator) Equal(a, b int) bool { return a == b }
こっちは,もちろんインライン化される.基本的にGenerics型のメソッドはインライン化されないみたい.
実際には,Comparatorを型引数として色々な処理に渡していて, 空のstructならインライン展開されていれば実行時のコストは全くかからないと思ったのだけど,毎回レシーバを指定したメソッド呼び出しになってしまっていた.これならstructではなく関数を値として取り回した方が少し良さそう.
一応,main.SimpleComparator[go.shape.int_0]
みたいな型が生成されて使われてるので,将来改善されそうだし,ほとんどの場合は気にならないけど.
そういえば,Goが出力するアセンブリ,引数が全部スタックに積まれてた時代はCPUアーキテクチャほとんど意識せず読めたのが,1.17からレジスタベースのABIになってアーキテクチャごとのレジスタの用途を知らないと読みにくくなってしまった.