Go Wiki: コンパイラとランタイムの最適化
このページでは、コンパイラによって行われる最適化をリストします。これらは言語仕様によって保証されるものではないことに注意してください。
インターフェース値
インターフェース値におけるゼロ幅型
ゼロ幅型をインターフェース値に入れる場合、アロケーションは発生しません。
- gc 1.0+
- gccgo ?
インターフェース値におけるワードサイズの値
ワードサイズ以下の非ポインター型をインターフェース値に入れる場合、アロケーションは発生しません。
- gc: 1.0-1.3、ただし1.4以降ではなし
- gccgo: なし
string と []byte
[]byte によるマップルックアップ
型 map[string]T のマップ m と []byte b について、m[string(b)] はアロケーションを発生させません。(バイトスライスのテンポラリな文字列コピーは作成されません)
- gc 1.4+
- gccgo ?
[]byte の range
バイトを範囲指定するために string を []byte に変換する場合、アロケーションは発生しません
s := "foo"
for i, c := range []byte(s) {
// ...
}
文字列比較のための変換
比較目的で []byte を string に変換する場合、アロケーションは発生しません
var b1 string
var b2 []byte
var x = string(b1) == string(b2) // memeq
var y = string(b1) < string(b2) // lexicographical comparison
- gc: 1.5以降 (CL 3790)
- gccgo ?
エスケープ解析とインライン化
gc ツールチェインのエスケープ解析とインライン化の決定の結果を観察するには、-gcflags -m を使用します。
(TODO: -gcflags -m の出力について説明する)
エスケープ解析
Gc コンパイラは、関数とパッケージの境界を越えてグローバルなエスケープ解析を実行します。ただし、解析をあきらめるケースが多数あります。たとえば、いかなる種類の間接参照 (*p = ...) にも割り当てられたものはエスケープされたとみなされます。解析を妨げるその他の要因には、関数呼び出し、パッケージ境界、スライスリテラル、サブスライシングとインデックス付けなどがあります。完全なルールは記述するには複雑すぎるため、-m の出力を確認してください。
- gc 1.0+
- gccgo 8.0+.
関数インライン化
短くシンプルな関数のみがインライン化されます。インライン化されるには、関数は以下のルールに準拠する必要があります。
- 関数は十分にシンプルであること、AST ノードの数が予算 (80) 未満であること。
- 関数がクロージャ、defer、recover、select などの複雑なものを含んでいないこと。
- 関数が go:noinline でプレフィックスされていないこと。
- 関数が go:uintptrescapes でプレフィックスされていないこと。インライン化中にエスケープ情報が失われるため。
- 関数に本体があること。
- など。
- gc 1.0+
- gccgo: -O1 以上。
イディオム
最適化された memclr
スライスまたは配列 s の場合、次の形式のループ
for i := range s {
s[i] = <zero value for element of s>
}
は効率的なランタイム memclr 呼び出しに変換されます。Issue および commit。
- gc 1.5+
- gccgo ?
スキャン不可能なオブジェクト
要素型にポインターが含まれない場合 (マップの場合はキーと値の両方)、ガベージコレクターはスライス、チャネル、マップの基になるバッファをスキャンしません。これにより、ガベージコレクション中に高いコストを支払うことなく、大量のデータをメモリに保持することができます。たとえば、以下のマップは GC 時間に目に見える影響を与えません。
type Key [64]byte // SHA-512 hash
type Value struct {
Name [32]byte
Balance uint64
Timestamp int64
}
m := make(map[Key]Value, 1e8)
- gc 1.5+
- gccgo ?
このコンテンツはGo Wikiの一部です。