[インデックス 13460] ファイルの概要
このコミットは、Go言語のツールチェーンの一部であるcmd/pack
コマンド内の、使用されていないページングロジックを削除するものです。具体的には、アーカイブファイル(ar
形式)を扱うsrc/cmd/pack/ar.c
ファイルから、ディスクへのデータページング(一時的な退避)に関連するコードが大幅に削除されています。これにより、コードベースの整理と不要な複雑さの排除が図られています。
コミット
- コミットハッシュ:
eb1c03eacbbd1e3a8000972f338122dc9d5748b9
- 作者: Dave Cheney dave@cheney.net
- コミット日時: 2012年7月12日 木曜日 10:14:07 +1000
- 変更ファイル:
src/cmd/pack/ar.c
(1ファイル変更, 7行追加, 58行削除)
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/eb1c03eacbbd1e3a8000972f338122dc9d5748b9
元コミット内容
commit eb1c03eacbbd1e3a8000972f338122dc9d5748b9
Author: Dave Cheney <dave@cheney.net>
Date: Thu Jul 12 10:14:07 2012 +1000
cmd/pack: remove unused paging logic
This is the remainder of https://golang.org/cl/4601051.
Partially addresses issue 2705.
R=golang-dev, r, bradfitz, minux.ma
CC=golang-dev
https://golang.org/cl/6354066
変更の背景
このコミットの主な目的は、cmd/pack
ツール内に存在していた、もはや使用されていないページングロジックを削除することです。コミットメッセージには「This is the remainder of https://golang.org/cl/4601051.」とあり、これは以前の変更(Change List, CL)の残骸、つまりそのCLで開始されたクリーンアップ作業の続きであることを示唆しています。また、「Partially addresses issue 2705.」とあり、Goの課題追跡システムにおける特定の課題(issue 2705)に部分的に対応するものであることも示されています。
ただし、現在のGoプロジェクトのCLシステムやIssueトラッカーでgolang.org/cl/4601051
やissue 2705
を検索しても、このコミットの文脈に直接関連する明確な情報は得られませんでした。golang.org/cl/4601051
は2022年の別のCLを指し、issue 2705
はVS CodeのGo拡張機能に関する問題を示しています。これは、2012年当時のGoプロジェクトの内部的なCL/Issue管理システムが現在とは異なっていたか、あるいは参照されているIDが現在では有効でないか、別の文脈で使われている可能性が高いことを示唆しています。
したがって、このコミットの直接的な背景は、Goツールチェーンの進化に伴い、cmd/pack
における特定のメモリ管理戦略(ページング)が不要になったため、その関連コードを削除し、コードベースを簡潔に保つためのクリーンアップ作業であると理解するのが適切です。特に、削除されたpage
関数の実装がsysfatal("page")
となっていたことから、このページング機能は実際には機能していなかったか、開発中に放棄された機能であった可能性が高いです。
前提知識の解説
cmd/pack
cmd/pack
は、Go言語の初期のツールチェーンの一部として存在していたコマンドです。その主な機能は、Unix系のシステムで広く使われているar
(archiver)形式のアーカイブファイルを操作することでした。Goのビルドプロセスにおいて、コンパイルされたGoパッケージのオブジェクトファイル(.a
ファイル)をまとめるために使用されていました。これは、C言語のリンカがGoのコードを扱う際に、Goのオブジェクトファイルを標準的なアーカイブ形式で提供する必要があったためと考えられます。現代のGoのビルドシステムでは、このcmd/pack
のような低レベルのアーカイブ操作は、より高レベルのツールによって抽象化され、開発者が直接意識することはほとんどありません。
ar
(archiver)
ar
は、Unix系オペレーティングシステムで複数のファイルを単一のアーカイブファイルにまとめるためのユーティリティです。主に静的ライブラリ(.a
ファイル、Windowsでは.lib
)を作成するために使用されます。静的ライブラリは、コンパイルされたオブジェクトファイル(.o
ファイル)の集合であり、プログラムのリンク時に実行可能ファイルに直接組み込まれます。ar
コマンドは、アーカイブの作成、メンバーの追加・削除、内容のリスト表示などの機能を提供します。
ページングロジック (Paging Logic)
コンピュータサイエンスにおける「ページング」は、仮想記憶管理の主要な手法の一つです。プログラムが物理メモリよりも大きなメモリ空間を必要とする場合、オペレーティングシステムはプログラムのメモリ空間を「ページ」と呼ばれる固定サイズのブロックに分割し、これらのページを必要に応じて物理メモリとディスクの間で移動(ページイン/ページアウト)させます。これにより、物理メモリの制約を超えて大きなプログラムを実行できるようになります。
このコミットで削除された「ページングロジック」は、cmd/pack
がアーカイブファイルを処理する際に、ファイルの内容をすべてメモリに読み込むのではなく、必要に応じてディスクから読み書きすることでメモリ使用量を抑えようとする試みであったと考えられます。大規模なアーカイブファイルを扱う場合、メモリが不足する可能性があり、その対策としてこのようなページング機構が検討されたのかもしれません。しかし、Goのツールチェーンの設計や、cmd/pack
が実際に扱うアーカイブファイルのサイズが、この複雑なページングロジックを必要としない程度であったため、最終的に不要と判断され削除されたと推測されます。
技術的詳細
このコミットは、src/cmd/pack/ar.c
ファイルに対して行われた変更であり、GoのツールチェーンがまだC言語で書かれたコンポーネントを含んでいた時代のものです。削除されたコードは、主にArfile
構造体、関連する関数プロトタイプ、およびそれらの関数の実装から構成されています。
-
Arfile
構造体からのフィールド削除:int paged;
: アーカイブファイルの一部がディスクにページアウトされたかどうかを示すフラグ。int fd;
: ページアウトされたデータが保存されている一時ファイルのファイルディスクリプタ。 これらのフィールドが削除されたことで、Arfile
構造体はもはやページングの状態や一時ファイルの管理を行う必要がなくなりました。
-
関数プロトタイプ宣言の削除:
int getspace(void);
int page(Arfile*);
これらの関数は、メモリが不足した際にページングによってスペースを確保しようとするロジックの一部でした。プロトタイプ宣言の削除は、これらの関数がコードベース全体から完全に除去されることを意味します。
-
arstream
関数からのページング処理の削除:arstream
関数は、アーカイブの内容をストリームとして出力する役割を担っていました。この関数内にあった以下のコードブロックが削除されました。if (ap->paged) { /* copy from disk */ seek(ap->fd, 0, 0); for (;;) { i = read(ap->fd, buf, sizeof(buf)); if (i < 0) rderr(); if (i == 0) break; if (write(fd, buf, i) != i) wrerr(); } close(ap->fd); ap->paged = 0; }
このブロックは、もしアーカイブデータがディスクにページアウトされていた場合、その一時ファイルからデータを読み込み、出力ストリームに書き出す処理を行っていました。この削除により、
arstream
はメモリ内のバッファ(in-core buffers
)のみを処理するようになりました。 -
page
関数とgetspace
関数の定義の削除:page
関数は、特定のArfile
構造体の内容をディスクにページアウトする役割を担っていました。しかし、その実装は単にsysfatal("page")
とされており、これは「ページング機能は実装されていないか、意図的に無効化されている」ことを示唆しています。つまり、この機能は実際には動作していなかったか、デバッグ目的で残されていたスタブであった可能性が高いです。getspace
関数は、メモリを解放するためにpage
関数を呼び出すロジックを持っていましたが、これもpage
関数が機能しないため、実質的に無意味でした。これらの関数の定義全体が削除されました。 -
armalloc
関数からのgetspace
呼び出しの削除:armalloc
関数は、アーカイブメンバーのためのメモリを確保するカスタムアロケータでした。以前は、malloc
が失敗した場合にgetspace()
を呼び出してメモリを解放しようとするdo...while
ループを持っていました。do { cp = malloc(n); if (cp) { memset(cp, 0, n); return cp; } } while (getspace());
このループが削除され、シンプルな
malloc
呼び出しに置き換えられました。cp = malloc(n); if (cp) { memset(cp, 0, n); return cp; }
これは、ページングによるメモリ解放の試みが完全に放棄されたことを意味します。メモリ確保に失敗した場合、もはや
getspace
を介した回復は試みられず、直接エラーメッセージを出力して終了するようになりました。
これらの変更は、cmd/pack
が扱うアーカイブファイルのサイズが、もはや複雑なページングロジックを必要としない程度になったか、あるいはGoのツールチェーン全体でより効率的なメモリ管理戦略が導入されたため、この特定のページング実装が不要になったことを明確に示しています。特に、page
関数のsysfatal
実装は、この機能が開発段階で放棄されたか、あるいは単にプレースホルダーであったことを強く示唆しています。
コアとなるコードの変更箇所
src/cmd/pack/ar.c
ファイルにおける主要な変更点は以下の通りです。
--- a/src/cmd/pack/ar.c
+++ b/src/cmd/pack/ar.c
@@ -77,9 +77,7 @@ typedef struct Armember /* Temp file entry - one per archive member */
typedef struct Arfile /* Temp file control block - one per tempfile */
{
- int paged; /* set when some data paged to disk */
char *fname; /* paging file name */
- int fd; /* paging file descriptor */
vlong size;
Armember *head; /* head of member chain */
Armember *tail; /* tail of member chain */
@@ -159,7 +157,6 @@ int bamatch(char*, char*);
int duplicate(char*, char**);
Armember *getdir(Biobuf*);
void getpkgdef(char**, int*);
-int getspace(void);
void install(char*, Arfile*, Arfile*, Arfile*, int);
void loadpkgdata(char*, int);
void longt(Armember*);
@@ -169,7 +166,6 @@ Arfile *newtempfile(char*);
Armember *newmember(void);
void objsym(Sym*, void*);
int openar(char*, int, int);
-int page(Arfile*);
void pmode(long);
void rl(int);
void scanobj(Biobuf*, Arfile*, long);
@@ -1534,24 +1530,8 @@ void
arstream(int fd, Arfile *ap)
{
Armember *bp;
- int i;
- char buf[8192];
-
- if (ap->paged) { /* copy from disk */
- seek(ap->fd, 0, 0);
- for (;;) {
- i = read(ap->fd, buf, sizeof(buf));
- if (i < 0)
- rderr();
- if (i == 0)
- break;
- if (write(fd, buf, i) != i)
- wrerr();
- }
- close(ap->fd);
- ap->paged = 0;
- }
- /* dump the in-core buffers */
+
+ /* dump the in-core buffers */
for (bp = ap->head; bp; bp = bp->next) {
if (!arwrite(fd, bp))
wrerr();
@@ -1576,35 +1556,6 @@ arwrite(int fd, Armember *bp)
return 1;
}
-/*
- * Spill a member to a disk copy of a temp file
- */
-int
-page(Arfile *ap)
-{
- USED(ap);
-
- sysfatal("page");
- return 1;
-}
-
-/*
- * try to reclaim space by paging. we try to spill the start, middle,
- * and end files, in that order. there is no particular reason for the
- * ordering.
- */
-int
-getspace(void)
-{
- if (astart && astart->head && page(astart))
- return 1;
- if (amiddle && amiddle->head && page(amiddle))
- return 1;
- if (aend && aend->head && page(aend))
- return 1;
- return 0;
-}
-
void
arfree(Arfile *ap) /* free a member buffer */
{
@@ -1633,13 +1584,11 @@ armalloc(int n)
if(n&1)
n++;
- do {
- cp = malloc(n);
- if (cp) {
- memset(cp, 0, n);
- return cp;
- }
- } while (getspace());
+ cp = malloc(n);
+ if (cp) {
+ memset(cp, 0, n);
+ return cp;
+ }
fprintf(2, "pack: out of memory\n");
exit("malloc");
return 0;
コアとなるコードの解説
このコミットは、src/cmd/pack/ar.c
ファイルから、アーカイブメンバーをディスクにページング(一時的に退避)する機能に関連するコードを完全に削除しています。
-
Arfile
構造体からのpaged
とfd
フィールドの削除:Arfile
構造体は、一時的なアーカイブファイルを制御するためのブロックです。以前は、paged
というフラグとfd
というファイルディスクリプタを持っていました。paged
は、そのファイルの一部がディスクにページアウトされたかどうかを示し、fd
はそのページアウトされたデータが保存されている一時ファイルのハンドルでした。これらのフィールドが削除されたことで、Arfile
はもはやディスクページングの状態を管理する必要がなくなりました。これは、ページング機能が完全に廃止されたことを意味します。 -
getspace
関数とpage
関数の削除:page(Arfile *ap)
関数は、アーカイブメンバーをディスク上の一時ファイルに書き出す(ページアウトする)ことを意図していました。しかし、その実装はsysfatal("page")
となっており、これは「この機能は致命的なエラーを引き起こすため、呼び出されるべきではない」という意味です。つまり、このページング機能は実際には実装されていなかったか、開発中に放棄された機能であった可能性が非常に高いです。getspace(void)
関数は、メモリが不足した際にpage
関数を呼び出すことで、メモリを解放しようと試みる役割を担っていました。page
関数が機能しないため、getspace
も実質的に無意味でした。 これらの関数の削除は、未実装または不要なページングロジックをコードベースから完全に排除するものです。
-
arstream
関数からのディスクページング処理の削除:arstream
関数は、アーカイブの内容をストリームとして出力する際に、もしデータがディスクにページアウトされていれば、一時ファイルから読み込んで出力するロジックを持っていました。このロジックが削除されたことで、arstream
はメモリ内のデータのみを処理するようになり、ディスクページングの概念が完全に排除されました。 -
armalloc
関数からのgetspace
呼び出しの削除:armalloc
は、cmd/pack
が内部で使用するメモリ確保関数です。以前は、malloc
がメモリ確保に失敗した場合、getspace()
を呼び出してメモリを解放しようと試みるループを持っていました。このループが削除され、malloc
が失敗した場合は直接エラーメッセージを出力して終了するようになりました。これは、ページングによるメモリ回復の試みが完全に放棄され、よりシンプルなメモリ管理戦略が採用されたことを示しています。
これらの変更は、Goのツールチェーンが進化し、cmd/pack
が扱うアーカイブファイルのサイズや、システム全体のメモリ管理能力が向上したため、複雑で未実装であったページングロジックが不要になったことを示唆しています。コードの簡素化と保守性の向上がこのコミットの主な成果です。
関連リンク
- GitHub上のコミットページ: https://github.com/golang/go/commit/eb1c03eacbbd1e3a8000972f338122dc9d5748b9
- Go言語公式ウェブサイト: https://go.dev/
- Go言語のソースコードリポジトリ (GitHub): https://github.com/golang/go
参考にした情報源リンク
- Web検索結果:
golang.org/cl/4601051
(このコミットの文脈とは異なるCLを指している可能性が高い) - Web検索結果:
golang issue 2705
(このコミットの文脈とは異なるIssueを指している可能性が高い) - Unix
ar
コマンドに関する一般的な情報源 (例:man ar
) - メモリページングに関する一般的なコンピュータサイエンスの知識