Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14762] ファイルの概要

このコミットは、Go言語のビルドシステムの一部である cmd/dist において、ブートストラッププロセス中にGCCコンパイラに -pipe オプションを使用するように変更を加えるものです。これにより、コンパイル時のパフォーマンスが向上し、特にディスクI/Oがボトルネックとなる環境でのビルド時間の短縮が期待されます。

コミット

commit 0c6beb00fbe00b843030f7a1178dfbc23a8e63d6
Author: Dave Cheney <dave@cheney.net>
Date:   Sun Dec 30 10:33:33 2012 +1100

    cmd/dist: use -pipe during bootstrap

    R=golang-dev, minux.ma, rsc
    CC=golang-dev
    https://golang.org/cl/7025044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/0c6beb00fbe00b843030f7a1178dfbc23a8e63d6

元コミット内容

cmd/dist: ブートストラップ中に -pipe を使用する

変更の背景

Go言語のビルドプロセス、特にブートストラップフェーズでは、Cコンパイラ(この場合はGCC)が使用されます。従来のコンパイルプロセスでは、コンパイラの各ステージ(プリプロセッサ、コンパイラ、アセンブラなど)が中間ファイルをディスクに書き込み、次のステージがそれを読み込むというI/Oが発生していました。このディスクI/Oは、特に大規模なプロジェクトやI/O性能が低いシステムにおいて、ビルド時間のボトルネックとなる可能性がありました。

このコミットは、GCCの -pipe オプションを導入することで、このディスクI/Oのオーバーヘッドを削減し、ビルドパフォーマンスを向上させることを目的としています。

前提知識の解説

Go言語のブートストラップ (Bootstrap)

Go言語は、自身のコンパイラやツールチェインをGo言語自身で記述しています。そのため、Go言語の新しいバージョンをビルドする際には、まず既存の(通常は以前のバージョンの)Goコンパイラを使用して、新しいバージョンのコンパイラ自身をコンパイルする必要があります。この自己コンパイルのプロセスを「ブートストラップ」と呼びます。

ブートストラッププロセスでは、GoのソースコードがC言語のコードに変換され、その後Cコンパイラ(GCCやClangなど)によってコンパイルされます。このCコンパイラによるコンパイルフェーズにおいて、本コミットの変更が適用されます。

cmd/dist

cmd/dist は、Go言語のソースコードからGoツールチェイン全体をビルドするためのコマンドです。これはGoのビルドシステムの中核をなし、コンパイラ、リンカ、アセンブラなどのツールを構築する役割を担っています。cmd/dist は、Goのブートストラッププロセスを管理し、Cコンパイラを呼び出してGoのランタイムやその他のCベースのコンポーネントをコンパイルします。

GCCの -pipe オプション

GCC (GNU Compiler Collection) は、C、C++、Goなど様々なプログラミング言語をサポートするコンパイラ群です。-pipe オプションは、GCCにコンパイルの各ステージ間で中間ファイルをディスクに書き込む代わりに、パイプ(メモリ上のデータストリーム)を使用して直接データを渡すように指示するオプションです。

通常、GCCは以下のような多段階のプロセスでコンパイルを行います。

  1. プリプロセッサ (cpp): ソースコードを前処理し、マクロ展開やインクルードファイルの処理を行います。結果は一時ファイルに書き込まれます。
  2. コンパイラ (cc1): プリプロセスされたコードをアセンブリコードに変換します。結果は一時ファイルに書き込まれます。
  3. アセンブラ (as): アセンブリコードをオブジェクトファイルに変換します。結果は一時ファイルに書き込まれます。
  4. リンカ (ld): オブジェクトファイルを結合し、実行可能ファイルを生成します。

-pipe オプションを使用すると、これらのステージ間での一時ファイルのディスク書き込みが省略され、メモリ上で直接データが受け渡されます。これにより、ディスクI/Oのオーバーヘッドが削減され、特にI/O性能が低いシステムや、多数の小さなファイルをコンパイルする際にビルド時間が短縮されます。

技術的詳細

このコミットは、src/cmd/dist/build.c ファイル内の proto_gccargs 配列に -pipe オプションを追加しています。proto_gccargs は、Goのブートストラッププロセス中にCコンパイラ(GCC)に渡されるデフォルトの引数リストを定義しています。

具体的には、以下の引数リストに -pipe が追加されました。

static char *proto_gccargs[] = {
	"-Werror",     // 警告をエラーとして扱う
	"-fno-common", // 共通ブロックの生成を抑制
	"-ggdb",       // GDBデバッグ情報を生成
	"-pipe",       // パイプを使用して中間ファイルを渡す
	"-O2",         // 最適化レベル2
};

この変更により、Goのブートストラップビルドにおいて、Cコンパイラがソースファイルをコンパイルする際に、各コンパイルステージ間でディスクI/Oを介さずにメモリ上でデータを直接やり取りするようになります。これにより、特にディスクの読み書きが頻繁に発生するような環境や、多数の小さなCファイルがコンパイルされる場合に、ビルド時間の短縮効果が期待できます。

-pipe オプションは、コンパイルプロセスを高速化する一方で、メモリ使用量が増加する可能性があります。しかし、現代のシステムでは通常、このメモリ増加は許容範囲内であり、ビルド時間の短縮というメリットの方が大きいと判断されたと考えられます。

コアとなるコードの変更箇所

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -396,6 +396,7 @@ static char *proto_gccargs[] = {
 	"-Werror",
 	"-fno-common",
 	"-ggdb",
+	"-pipe",
 	"-O2",
 };

コアとなるコードの解説

変更は src/cmd/dist/build.c ファイルの proto_gccargs という静的文字列配列に対して行われています。この配列は、Goのブートストラッププロセス中にCコンパイラ(GCC)を呼び出す際に使用されるコマンドライン引数を定義しています。

追加された行 + "-pipe", は、この配列に -pipe という文字列リテラルを追加しています。これにより、cmd/dist がGCCを呼び出す際に、他の引数(-Werror, -fno-common, -ggdb, -O2 など)と共に -pipe オプションが渡されるようになります。

結果として、GoのブートストラップビルドにおけるCコンパイルフェーズが、ディスクI/Oを削減し、より効率的に実行されるようになります。

関連リンク

参考にした情報源リンク