Open4

6 simple ways to optimise Golang を読む

Shunsuke SuzukiShunsuke Suzuki

名前付き戻り値を使うとパフォーマンスが改善する

named return か否かで生成されるコードが変わるらしい。
同じコードを生成するようにしようという issue が 5 年くらい前からあるが、 open のまま。
もしかしたら改善されている部分もあるのかもしれない。

https://github.com/golang/go/issues/20859

https://medium.com/@ramseyjiang_22278/90-of-gophers-dont-know-6-simplest-ways-to-optimise-code-2-83d5f1f06272

https://postd.cc/golang-internals-part-2-nice-benefits-of-named-return-values/

Shunsuke SuzukiShunsuke Suzuki

文字列の結合には strings.Builder を使え

https://medium.com/@ramseyjiang_22278/join-string-using-strings-builder-6-simple-ways-to-optimise-golang-4-59f3fdf630f

+ や fmt.Sprintf よりも strings.Builder のほうがパフォーマンス的に良いらしい

https://pkg.go.dev/strings#Builder

確かにパフォーマンス的に良さそうな事が書いてある

A Builder is used to efficiently build a string using Write methods. It minimizes memory copying

non-zero な Builder をコピーするなとも書いてある

The zero value is ready to use. Do not copy a non-zero Builder


記事中のコードをよく見ると sb.String() がベンチマークの外で呼ばれているので、ベンチマークとしてはあまり適切ではなさそう。

log.Printf("joinStrWithBuilderForLoop ExecTime is %22s %6s\n", "->", time.Since(execTime))
return sb.String()

話がずれるが、 fmt.Sprintf が + よりもパフォーマンスが良いというのは意外だった。てっきり + のほうがいいのかと思いこんでいた。 fmt.Sprintf を避けて + を使ったりしていたが、むしろ fmt.Sprintf を使ったほうがいいのかもしれない。


https://qiita.com/po3rin/items/2e406645e0b64e0339d3

Shunsuke SuzukiShunsuke Suzuki

for range の代わりに for loop を使え

https://medium.com/@ramseyjiang_22278/in-my-previous-article-i-mentioned-there-are-6-simple-ways-to-help-you-to-optimise-golang-code-81c013f70ca4

for range は要素の構造体のフィールド数が増えるとパフォーマンスが悪化するが、 for loop では要素の型が変わってもパフォーマンスはほとんど変わらない。


この件に関連する日本語のソースなどはぱっと見つからない。

下記の記事では、 for range のほうが最適化が効いて速くなるみたいなことが書いてある気がするが、
ちょっとまだちゃんと読めていない。

https://betterprogramming.pub/handling-large-arrays-in-golang-should-you-use-for-range-or-for-loop-9995a02fd316

Shunsuke SuzukiShunsuke Suzuki

ちなみに、この連載に関して最初に思ったこととして、
パフォーマンスについて語るのであれば、一回実行しただけの処理時間を比較するのではなく、
testing.B を使って Benchmark Test をすべきだと思う。

https://pkg.go.dev/testing#hdr-Benchmarks

以前 aqua で benchmark test をした際のコード
https://github.com/aquaproj/aqua/blob/b0132712bd0dd3ea1cd440acedc75cab081fb723/pkg/config/registry_test.go#L105-L186

と思ったら、以下の記事では Benchmark Test をしていた。

https://medium.com/@ramseyjiang_22278/in-my-previous-article-i-mentioned-there-are-6-simple-ways-to-help-you-to-optimise-golang-code-81c013f70ca4