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

[インデックス 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/4601051issue 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構造体、関連する関数プロトタイプ、およびそれらの関数の実装から構成されています。

  1. Arfile構造体からのフィールド削除:

    • int paged;: アーカイブファイルの一部がディスクにページアウトされたかどうかを示すフラグ。
    • int fd;: ページアウトされたデータが保存されている一時ファイルのファイルディスクリプタ。 これらのフィールドが削除されたことで、Arfile構造体はもはやページングの状態や一時ファイルの管理を行う必要がなくなりました。
  2. 関数プロトタイプ宣言の削除:

    • int getspace(void);
    • int page(Arfile*); これらの関数は、メモリが不足した際にページングによってスペースを確保しようとするロジックの一部でした。プロトタイプ宣言の削除は、これらの関数がコードベース全体から完全に除去されることを意味します。
  3. 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)のみを処理するようになりました。

  4. page関数とgetspace関数の定義の削除: page関数は、特定のArfile構造体の内容をディスクにページアウトする役割を担っていました。しかし、その実装は単にsysfatal("page")とされており、これは「ページング機能は実装されていないか、意図的に無効化されている」ことを示唆しています。つまり、この機能は実際には動作していなかったか、デバッグ目的で残されていたスタブであった可能性が高いです。 getspace関数は、メモリを解放するためにpage関数を呼び出すロジックを持っていましたが、これもpage関数が機能しないため、実質的に無意味でした。これらの関数の定義全体が削除されました。

  5. 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ファイルから、アーカイブメンバーをディスクにページング(一時的に退避)する機能に関連するコードを完全に削除しています。

  1. Arfile構造体からのpagedfdフィールドの削除: Arfile構造体は、一時的なアーカイブファイルを制御するためのブロックです。以前は、pagedというフラグとfdというファイルディスクリプタを持っていました。pagedは、そのファイルの一部がディスクにページアウトされたかどうかを示し、fdはそのページアウトされたデータが保存されている一時ファイルのハンドルでした。これらのフィールドが削除されたことで、Arfileはもはやディスクページングの状態を管理する必要がなくなりました。これは、ページング機能が完全に廃止されたことを意味します。

  2. getspace関数とpage関数の削除:

    • page(Arfile *ap)関数は、アーカイブメンバーをディスク上の一時ファイルに書き出す(ページアウトする)ことを意図していました。しかし、その実装はsysfatal("page")となっており、これは「この機能は致命的なエラーを引き起こすため、呼び出されるべきではない」という意味です。つまり、このページング機能は実際には実装されていなかったか、開発中に放棄された機能であった可能性が非常に高いです。
    • getspace(void)関数は、メモリが不足した際にpage関数を呼び出すことで、メモリを解放しようと試みる役割を担っていました。page関数が機能しないため、getspaceも実質的に無意味でした。 これらの関数の削除は、未実装または不要なページングロジックをコードベースから完全に排除するものです。
  3. arstream関数からのディスクページング処理の削除: arstream関数は、アーカイブの内容をストリームとして出力する際に、もしデータがディスクにページアウトされていれば、一時ファイルから読み込んで出力するロジックを持っていました。このロジックが削除されたことで、arstreamはメモリ内のデータのみを処理するようになり、ディスクページングの概念が完全に排除されました。

  4. armalloc関数からのgetspace呼び出しの削除: armallocは、cmd/packが内部で使用するメモリ確保関数です。以前は、mallocがメモリ確保に失敗した場合、getspace()を呼び出してメモリを解放しようと試みるループを持っていました。このループが削除され、mallocが失敗した場合は直接エラーメッセージを出力して終了するようになりました。これは、ページングによるメモリ回復の試みが完全に放棄され、よりシンプルなメモリ管理戦略が採用されたことを示しています。

これらの変更は、Goのツールチェーンが進化し、cmd/packが扱うアーカイブファイルのサイズや、システム全体のメモリ管理能力が向上したため、複雑で未実装であったページングロジックが不要になったことを示唆しています。コードの簡素化と保守性の向上がこのコミットの主な成果です。

関連リンク

参考にした情報源リンク

  • Web検索結果: golang.org/cl/4601051 (このコミットの文脈とは異なるCLを指している可能性が高い)
  • Web検索結果: golang issue 2705 (このコミットの文脈とは異なるIssueを指している可能性が高い)
  • Unix arコマンドに関する一般的な情報源 (例: man ar)
  • メモリページングに関する一般的なコンピュータサイエンスの知識