前回の記事では,
Why my Go program is slow? (@methane氏)
このセッションでは,pprof
というCPUプロファイラとGo言語におけるパフォーマンスチューニングについての話がされました。なお,
サンプリングプロファイラ
pprof
はサンプリングプロファイラで,
用途に適したパッケージを使う
同氏は,runtime/
を直接使用するのではなく,net/
を使用すると良いと主張していました。なお,net/
は以下のようにimport
するだけで使えるそうです。
import (
"net/http"
_ "net/http/pprof"
)
func main() {
go http.ListenAndServe(":5000", nil)
}
また同氏は,davecheney/
を使うと良いと述べていました。
Macでサンプリングプロファイラを使用するためには
pprof
はSIGPROF
というシグナルを送る機能を利用しているそうですが,pprof
を利用できないそうです。この件の詳細は,pprof
できるようにしているそうです。なお,
methane氏は,
go tool pprof
runtime/
およびnet/
でプロファイリングした結果は,go tool pprof
を使って解析することができるそうです。元々このツールは,perftools
を利用していたそうですが,go tool pprof
を使うことを同氏は推奨していました。このセッションでは,pprof
を使ってプロファイリングをするデモが行われました。pprof
の使い方については,
- http://
blog. golang. org/ profiling-go-programs - https://
software. intel. com/ en-us/ blogs/ 2014/ 05/ 10/ debugging-performance-issues-in-go-programs
Go言語で書かれたプログラムが遅くなる理由
同氏は,
- ガベージコレクション
(GC) - メモリコピー
- 関数呼び出し
ガベージコレクション (GC)
GCが重い場合は,GODEBUG=gctrace=1
というデバッグフラグを付けるとGCの情報が見られるそうです。また,pprof
のヒープのプロファイラを使うと,sync.
を使ってオブジェクトをプールしておき,
また,make
関数で指定すると,GOGC
という環境変数の値を大きくすることで,
なお,
メモリコピー
string
型で持っている値を実際に使う際に頻繁に[]byte
型に変換
する場合,[]byte
型で値を持つと良いと述べていました。また,net/
パッケージのReader.
で行われているテクニックについての説明がされていました。
なお,Reader.
については同氏の記事で詳しく解説されています。
関数呼び出し
同氏は以下の理由により,
- 引数や戻り値がレジスタではなくスタック渡しであるため
- 呼び出す側が使用しているすべてのレジスタを退避させる必要があるため
- 関数呼び出し時にゴルーチンの切り替えやGCのストップザワールドのために起こるランタイムのフックがあるため
一方で,