こんにちは。Tomoyuki(@tomoyuki65)です。
Go言語(Golang)にはimportすることで使用できる標準パッケージが色々ありますが、その中にはGoのプログラム実行時の動作を制御したり観察するための標準パッケージとして「runtime」があります。
この記事では、そんな「runtime」パッケージについてご紹介します。
Go言語(Golang)のruntimeパッケージについて
runtimeパッケージは、Goのランタイムシステム(Goプログラムの実行中にメモリ管理や並行処理などを自動的に行う仕組みで、コンパイルされたバイナリの中に組み込まれて動作する実行時の基盤)と直接やりとりするためのAPI群を提供しており、以下のような低レベル機能があります。
・メモリ管理・ガーベジコレクション(GC)
・システム情報・実行環境情報
・panic / recover・スタック情報
・内部動作に関わる機能(特殊)
ゴルーチンとスケジューラ関連
平行処理やスケジューリング制御をより細かく行いたい場合などに、Goラインタイムの並行実行エンジン(スケジューラ)を直接操作できます。
・実行中のゴルーチン数を取得する例
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("ゴルーチン数:", runtime.NumGoroutine())
}
実行結果(結果は環境によります)
ゴルーチン数: 1
メモリ管理・ガーベジコレクション(GC)
パフォーマンス計測、Cライブラリとのやり取り、安全なリソース解放などを目的として、メモリ使用状況を調べたり、GCを制御することができます。
・メモリ使用状況を取得する例
package main
import (
"fmt"
"runtime"
)
// バイトをMBに変換する関数
func byteToMB(b uint64) float64 {
return float64(b) / 1024 / 1024
}
func main() {
// メモリ使用状況の取得
var m runtime.MemStats
runtime.ReadMemStats(&m)
// 現在ヒープで使用中のバイト数(まだ解放されていない)
fmt.Printf("Alloc = %.2f MB\n", byteToMB(m.Alloc))
// 累計割り当てバイト数(解放済み含む)
fmt.Printf("TotalAlloc = %.2f MB\n", byteToMB(m.TotalAlloc))
// OSから確保された合計バイト数(ヒープ以外も含む)
fmt.Printf("Sys = %.2f MB\n", byteToMB(m.Sys))
// ヒープに割り当てられているバイト数(Allocとほぼ同じ)
fmt.Printf("HeapAlloc = %.2f MB\n", byteToMB(m.HeapAlloc))
// OSが確保しているヒープ領域全体のバイト数
fmt.Printf("HeapSys = %.2f MB\n", byteToMB(m.HeapSys))
}
実行結果(結果は環境によります)
Alloc = 0.11 MB
TotalAlloc = 0.11 MB
Sys = 7.46 MB
HeapAlloc = 0.11 MB
HeapSys = 3.69 MB
システム情報・実行環境情報
プログラムが動作している環境やOSに関する情報を取得できます。
・環境情報を取得する例
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Printf("利用可能なCPUコア数: %d\n", runtime.NumCPU())
fmt.Printf("Goランタイムのバージョン: %s\n", runtime.Version())
fmt.Printf("OS: %s\n", runtime.GOOS)
fmt.Printf("アーキテクチャ: %s\n", runtime.GOARCH)
}
実行結果(結果は環境によります)
利用可能なCPUコア数: 8
Goランタイムのバージョン: go1.25.4
OS: linux
アーキテクチャ: amd64
panic / recover・スタック情報
panic発生時などのデバッグやログ出力のため、現在のスタックトレースを取得できます。
・スタックトレースを取得する例
package main
import (
"fmt"
"runtime"
)
// テスト関数
func test() {
// スタックトレースを取得(呼び出したゴルーチンのみ)
buf := make([]byte, 1024)
n := runtime.Stack(buf, false)
// ログ出力
fmt.Printf("Stack trace of current goroutine:\n%s\n", buf[:n])
}
func main() {
// テスト関数を実行
test()
}
実行結果(結果は環境によります)
Stack trace of current goroutine:
goroutine 1 [running]:
main.test()
/tmp/sandbox675245624/prog.go:10 +0x3a
main.main()
/tmp/sandbox675245624/prog.go:15 +0xf
内部動作に関わる機能(特殊)
C言語関数呼び出し(Cgo)の回数取得や、低レベルなライブラリ実装やツールチェイン開発のための内部動作に関わる機能があります。
・プログラム実行中にCgoを通じて呼ばれたC関数の回数を取得する例
package main
import (
"fmt"
"runtime"
)
func main() {
// Cgoを通じて呼ばれたC関数の回数を取得(呼ばれてなければ0)
fmt.Printf("Cgo 呼び出し回数: %d\n", runtime.NumCgoCall())
}
実行結果
Cgo 呼び出し回数: 0
最後に
今回はGo言語(Golang)の「runtime」パッケージについてご紹介しました。
よく使うパッケージではありませんが、デバッグやパフォーマンス測定などで利用する可能性もあるため、こういったものがあるのを知っておくのは大事です。



コメント