Effective C++読書メモ #30

2015年4月30日木曜日

Item 30: Understanding the ins and outs of inlining.

これまでメモ無しで読んできていたのを他の本と同様にメモ残していくようにしたので今回から。Effective Objective-Cのメモとスタイルを揃えて通番途中からスタートしてみる。

インライン化の恩恵は関数っぽく扱えつつ関数呼び出しのオーバーヘッドがないというだけではない。コンパイラによるコンテキスト固有の最適化を追加でおこなえるかもしれない。逆に、コードサイズが増えてキャッシュミスしやすくなるかもしれない。インライン関数がかなり小さなものだったら、関数へコンパイルされるよりもコードが小さくなるかもしれない(スタックのpush/popとか無いのだし当然ではある)。

暗黙的なインライン関数の書き方があるの知らなかった。constで直値を返すアクセッサメソッドは勝手にinline扱いになるということなのかな。

テンプレートを考えなしにインライン化宣言するなという話もあったけれど、ちゃんと理解するにはC++力が足りなかった。そのうち戻ってこよう。

インライン化はコンパイラによって無視されうるという話。これ知らなかった。ループを含んだり再帰するようなものは無視する(そりゃそうか。これを安全にインライン化すると結局関数へ切り分けるのと同じかそれ以上に複雑なコード生成となりそう)。あと、virtualキーワードのついたもの(つまり実行時までどれが選択されるか分からないもの)もinlineできねーよとして無視される。言われてみると当然だった。

インライン関数のポインタを用意した場合などには、それに該当する実体が作成される。こうして整合性を取る(実体も別途用意されるの意かな)。

なんでもかんでもインライン化していいわけじゃないという話が続く。例としてctor/dtorが挙げられている。C++の仕様が求めることをコンパイラが実装した結果なにが起こるかという話。仮に空っぽのコンストラクタでも、フィールド初期化などはしてる。そしてその中で例外が起こったらすべて無かったことにしてくれる。これは裏側で例外処理時のコードを大量に生成してる。

ライブラリ構築時にはインライン化するか否かちゃんと考える必要がある。ライブラリの中身をインライン化してしまうと、ユーザの手元にあるそのコードをバイナリ差分として更新する手立てがない。焼きこまれてるんだから、当該コードを更新するためには再コンパイルが必要。インライン化されてなければ別バイナリをリンクし直すだけでok。この視点は無かったので役立つ。

デバッガの邪魔にもなる。これも気付いてなかった。言われると当然で、そもそも関数じゃないんだから単純にコールスタック追えない。まあプログラムカウンタはちゃんと分かる場所にあるはずなのでそれぐらい頑張ってほしいという気持ちではある。

まとめとして、明らかにインライン化すべき場所以外では使うなということだった。ここの処理コストを気にするほど全体は効率的に動かないじゃろというのが主なイメージ。

面白かった。

0 件のコメント:

コメントを投稿