【Go】スタックとヒープについて簡単なサンプルで確認する

Go

はじめに

メモリ領域にはスタックとヒープがあります。

スタックは関数呼び出しやその中で使われるローカル変数などが格納されるメモリ領域。

ヒープは動的にメモリが割り当てられる領域で、サイズの決まっていないデータや関数外で参照されたりする場合に使用するメモリ領域。

ヒープが大量に使用されてしまうと処理動作が遅くなるため、パフォーマンス改善をしていく際にこれらの知識が必要そうだったので、サンプルコードで確認したいと思います。

コード

package main

// スタック上に割り当て
func stackExample() int {
	x := 42
	y := x + 1
	return y
}

// ヒープ上に割り当て
func heapExample() *int {
	z := 42
	return &z
}

func main() {
	_ = stackExample()

	_ = heapExample()
}

動かしてみる

コンパイルする際に、-gcflags -mをつけると、エスケープ解析のログを出力することができます。

このエスケープ解析というもので変数をスタックからヒープに移動させるかどうかを判別しているようです。

go build -gcflags -m main.go

stackExampleのx,yはエスケープされていません。

heapExampleのzはポインタを返しており、関数外で参照される可能性があるためヒープに移動されています。

# command-line-arguments
./main.go:3:6: can inline stackExample
./main.go:9:6: can inline heapExample
./main.go:14:6: can inline main
./main.go:15:18: inlining call to stackExample
./main.go:17:17: inlining call to heapExample
./main.go:10:2: moved to heap: z