2014年6月28日土曜日

Golang Cafe #35を開催しました。

Golang Cafe #35を開催しました。

今回は、GoCon 2014 Springの時に発表されたDave Cheneyさんの資料
読み進めました。

今回の資料は、「Goのプログラムを早くする5つのこと」ということで話されたようです。
最初、参加者の全員が思っていたと思うのですが、「Goのプログラムを早くするために”プログラマ”がすればいいこと」が書かれていると思っていました。

しかし、中身は「Goのコンパイラがコードを解析してコンパイルしてリンクする時にやっていること」が書かれているようでした。
しかも、結構深い内容で、読む方も疲れてしまいました。(私だけかもしれませんが)

5つのうち、2つ目までを読み進めたので、そのまとめを書いておきます。

1つ目は"value"
ポイントは、Goでは、例えばint32の変数だと、正確に4バイトが確保されます。
ですが、Pythonだと、24バイト。Javaだと、16バイト(32bit版)か32バイト(64bit版)が確保されます。同じ、4バイト変数なのに。

で、これが重要な理由はなにか?というと、CPUとメモリのバスの速度差がでてくるようになった背景があって、メモリの転送時間がCPUの処理時間に比べて長いので、CPUが転送待ちになってしまうので、処理速度が上がらないわけです。

そこで、キャッシュの機構をCPUとメモリの間にいれてやれば早くなるわけですが、キャッシュの領域もそこまで大きくない。

ということで、コンパクトな構造体を作り、余計な間接部分を避けるようにGoのコンパイラが良いようにしてくれている。
コンパクトなデータ構造はキャッシュをしっかり使える。
これにより、より良いパフォーマンスを発揮できるようになっている。

ということでした。

2つ目は"inlining"
ここでのポイントは関数呼び出しをインライン化すること。
デッドコードの除去。

1つ目の関数呼び出しのオーバヘッドは回避できないので、Goのコンパイラはinline化できるものは、勝手にinline化しているようです。これにより、関数呼び出しのオーバーヘッドをなくしています。ですが、inline化は、「コピペ」であるわけですから、バイナリサイズは大きくなってしまいます。速度を求めるために、バイナリサイズが大きくなる事に目をつぶっているわけですね。
(個人的には、バイナリサイズが大きくなるとは言え、1ファイルになるのはいいことだと思うけど…。こだわりがある人はまた違う見解があるんだろうか。)

そして、デッドコードの除去に関しては、if(false) { ... }となるようなケースだと、「絶対にif文の中を通らないわけですから、なくしても構わない。ということで、思い切ってコンパイル時には外しているようです。
したがって、Debug用コードを書く場合は、単純にDebugフラグをtrueにして、本番環境ではDebugフラグをfalseにした状態にしてビルドすればいいわけです。
(ただし、オプション引数によってtrue/falseを切り替えるケースでは、デッドコードにならないので、除去されません。)

今回は、結構深くて重たい資料だったと思うのですが、がんばって読んでみると良いものだと思います。が、これは業務とかに利用するのは難しい気が…。

次回は、Google I/O 2014が終わったので、いろんな動画やCodelabの資料が公開されてきているので、動画を見たり、Codelabの資料を追いかける予定です。
(ただし、Goのセッションは今年はなかった…)