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の一部です。