Go 1.25、GOMAXPROCS自動設定の恩恵
先日公開されたGoの公式ブログ「Container-aware GOMAXPROCS」は、コンテナでGoを動かす開発者にとって良いアップデートの情報をご紹介をさせていただきます。
「docker run --cpus="2.0"
でCPUを制限しているのに、想定通りじゃなさそうだな…🤔」そんな経験はありませんか?
Go 1.25から、そのような課題がGoランタイム自身によって解決されます。この記事では、公式ブログの内容を基に、Dockerを触る開発者にとって具体的に何がどう変わるのかを解説します。
docker run --cpus
もあるけど不十分だった件
Dockerでアプリケーションを動かす際、--cpus
オプションでコンテナが使用できるCPUリソースを制限することができます。
しかし、従来のGoランタイムは、このDockerによる制限を認識できませんでした。Goはコンテナの外側、つまりホストマシン全体のCPUコア数を見てGOMAXPROCS
(並列実行スレッド数)を判断していました。
例えば、8コアのPC上で、--cpus="2.0"
オプションを付けてGoアプリのコンテナを起動した状況を考えてみましょう。
Goアプリは8コアあると信じて8スレッドを動かそうとしますが、Dockerからは2コア分のCPU時間しか与えられていません。このギャップにより、OSはGoアプリの処理を頻繁に中断(スロットリング)させ、結果としてパフォーマンスが大きく低下していました。
このため、私たちはこれまでENV GOMAXPROCS=2
をDockerfileに書き加えるなどの手動設定が必要でした。
Go 1.25でシンプルに解決!
公式ブログで解説されている通り、Go 1.25からはGoランタイムがコンテナのCPU制限を自動で認識するようになります。これはDockerが内部で利用しているLinuxのcgroupという仕組みをGoが直接解釈できるようになったためです。直接解釈してくれるのは最高👍
これにより、開発者の作業は劇的に変化しますね!
Go 1.24以前 | Go 1.25以降 | |
---|---|---|
挙動 | ホストマシンのCPUコア数を参照 |
docker run --cpus の値を自動認識 |
開発者の対応 |
GOMAXPROCS の手動設定が必要 |
原則、何もしなくてよい |
メリット | - | ・設定漏れの防止 ・Dockerfileの簡素化 ・パフォーマンスの自動最適化 |
Docker開発者にとっての具体的なメリット
docker run
コマンドの簡素化
1. Dockerfileと--cpus
の値に合わせてDockerfileを書き換えたり、docker run
時に-e
オプションで環境変数を渡す必要がなくなります。
Before (Dockerfileの例)
# --cpus=2.0 に合わせて手動で設定する必要があった
ENV GOMAXPROCS=2
CMD ["/app"]
After (Go 1.25)
# GOMAXPROCSの設定は不要。
# `docker run --cpus`の値に応じてランタイムが自動で判断する。
CMD ["/app"]
これにより、開発環境(--cpus
無制限)と本番環境(--cpus="1.0"
)でイメージやコマンドを使い分ける必要がなくなり、設定ミスが減りますね
automaxprocs
ライブラリが不要に
2. この問題を解決するために広く使われてきたuber-go/automaxprocs
というサードパーティライブラリがありましたが、Go 1.25からは標準機能として同等の機能が提供されるため、依存ライブラリを1つ減らすことができます。
3. パフォーマンスの安定化
ローカルのDockerでも、CI/CDパイプライン上のコンテナでも、常にその環境のCPUリソースに応じた最適なパフォーマンスが引き出せます。CPUスロットリングによる意図しない性能劣化を防ぎ、アプリケーションの動作を安定させることができます。
まとめ
Go1.25 GOMAXPROCSでコンテナ上のCPU管理が楽できる。
Dockerfileから GOMAXPROCS 設定を削除可能になる。
このような自動制御してくれる機能がアプリケーションの運用視点で喜ばしいことだと思います!!
参考情報
Discussion