[インデックス 15573] ファイルの概要
このコミットは、test/bench/garbage/parser.go ファイルに対する変更です。具体的には、このファイル内の packages スライスが更新され、77行が追加され、18行が削除されています。これにより、合計で95行の変更が発生しています。
コミット
commit 66a93729767d3c0e0e0bb5c90ae8369e1c06458f
Author: Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
Date: Mon Mar 4 16:46:04 2013 +0100
test/bench/garbage: fix parser benchmark
R=golang-dev, dvyukov
CC=golang-dev
https://golang.org/cl/7435053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/66a93729767d3c0e0e0bb5c90ae8369e1c06458f
元コミット内容
test/bench/garbage: fix parser benchmark
R=golang-dev, dvyukov
CC=golang-dev
https://golang.org/cl/7435053
変更の背景
このコミットの目的は、Go言語の標準ライブラリのベンチマークテストの一部である test/bench/garbage/parser.go のパーサーベンチマークを修正することです。コミットメッセージにある「fix parser benchmark」という記述から、既存のベンチマークが正しく機能していなかったか、あるいはGo言語の進化に伴い、ベンチマークの対象となるパッケージリストが古くなっていた可能性が示唆されます。
test/bench/garbage というパスは、Goのベンチマークスイートにおいて、ガベージコレクション(GC)のパフォーマンスやメモリ割り当ての挙動を評価するためのテストが含まれていることを示唆しています。パーサーベンチマークの場合、Goのソースコードを解析する際のメモリ使用量やGCの頻度を測定することが目的と考えられます。
この修正は、ベンチマークの対象となるパッケージリストを最新の状態に更新することで、より現実的で正確なパーサーのパフォーマンス測定を可能にすることを意図しています。
前提知識の解説
Go言語のベンチマーク
Go言語には、標準でベンチマークテストを記述・実行するためのフレームワークが組み込まれています。testing パッケージを使用し、BenchmarkXxx という形式の関数を記述することで、コードのパフォーマンスを測定できます。これらのベンチマークは、go test -bench=. コマンドで実行され、処理時間やメモリ割り当てなどの統計情報が出力されます。
go/parser パッケージ
go/parser パッケージは、Go言語のソースコードを解析し、抽象構文木(AST: Abstract Syntax Tree)を生成するための機能を提供します。Goのツールチェイン(コンパイラ、リンカ、フォーマッタなど)の基盤となる重要なパッケージの一つです。このコミットで修正されている「パーサーベンチマーク」は、おそらくこの go/parser パッケージの性能を測定していると考えられます。
ガベージコレクション (GC) とベンチマーク
Go言語は自動メモリ管理(ガベージコレクション)を採用しています。ベンチマークにおいて、GCの挙動は非常に重要です。特にパーサーのような、大量のオブジェクトを生成・破棄する可能性のある処理では、GCの効率が全体のパフォーマンスに大きく影響します。test/bench/garbage というディレクトリ名から、このベンチマークがGCの側面を特に重視していることがわかります。
var packages = []string{...}
Go言語における []string は文字列のスライス(動的配列)を意味します。このコミットで変更されている packages 変数は、Goの標準ライブラリに含まれるパッケージのパス(例: "archive/tar", "encoding/json" など)を文字列として保持するスライスです。パーサーベンチマークでは、これらのパッケージのソースコードを読み込み、解析することで、パーサーの性能を評価していると推測されます。
技術的詳細
このコミットの技術的な詳細は、test/bench/garbage/parser.go ファイル内の packages スライスの内容が大幅に更新された点に集約されます。
元の packages スライスには、Goの標準ライブラリのサブセットが含まれていましたが、このコミットによって、より多くのパッケージが追加され、一部のパッケージが削除されています。追加されたパッケージは、archive/zip, builtin, compress, compress/bzip2, compress/lzw, container, crypto, crypto/cipher, crypto/des, crypto/dsa, crypto/ecdsa, crypto/elliptic, crypto/x509/pkix, database, database/sql, database/sql/driver, debug, debug/pe, encoding, encoding/base32, encoding/csv, encoding/gob, encoding/json, encoding/xml, errors, expvar, go, go/build, go/format, go/types, hash/fnv, html, html/template, image/color, image/draw, image/gif, index, index/suffixarray, log/syslog, math/rand, mime/multipart, net, net/http/cgi, net/http/cookiejar, net/http/fcgi, net/http/httptest, net/http/httputil, net/http/pprof, net/mail, net/rpc, net/rpc/jsonrpc, net/smtp, net/textproto, net/url, os/exec, os/signal, os/user, path/filepath, regexp/syntax, runtime/cgo, runtime/debug, runtime/pprof, runtime/race, sync/atomic, syscall, text, text/template/parse, unsafe など、多岐にわたります。
削除されたパッケージは、encoding/asn1, math/big, math/cmplx, debug/macho, exp/ebnf, os/exec, encoding/gob, net/http, encoding/json, net/rpc, net/smtp, log/syslog, text/tabwriter, text/template, unicode/utf8, encoding/xml などです。ただし、これらの多くは、新しいリストで再度追加されているか、より具体的なサブパッケージに置き換えられています。
この変更の最も重要な点は、packages スライスの定義の直前に追加されたコメント行です。
// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
このコメントは、packages スライスがどのように生成されたかを示すシェルコマンドです。このコマンドは、Goリポジトリのルートディレクトリから、exp ディレクトリを除外し、testdata を含まないすべてのディレクトリ(Goパッケージに対応)を検索し、そのパスを整形してGoのスライス形式で出力するものです。
このことから、以前の packages リストは手動で管理されていたか、あるいは古いバージョンのGoのパッケージ構成を反映していた可能性があり、このコミットによって、Goの現在のパッケージ構成を自動的に反映するように更新されたことがわかります。これにより、パーサーベンチマークはGoの標準ライブラリ全体をより網羅的に対象とすることができ、より正確で代表的なパフォーマンスデータを提供できるようになります。
コアとなるコードの変更箇所
--- a/test/bench/garbage/parser.go
+++ b/test/bench/garbage/parser.go
@@ -134,20 +134,31 @@ func main() {
}
}
+// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
var packages = []string{
+\t"archive",
"archive/tar",
-\t"encoding/asn1",
-\t"math/big",
+\t"archive/zip",
"bufio",
+\t"builtin",
"bytes",
-\t"math/cmplx",
+\t"compress",
+\t"compress/bzip2",
"compress/flate",
"compress/gzip",
+\t"compress/lzw",
"compress/zlib",
+\t"container",
"container/heap",
"container/list",
"container/ring",
+\t"crypto",
"crypto/aes",
+\t"crypto/cipher",
+\t"crypto/des",
+\t"crypto/dsa",
+\t"crypto/ecdsa",
+\t"crypto/elliptic",
"crypto/hmac",
"crypto/md5",
"crypto/rand",
@@ -159,64 +170,112 @@ var packages = []string{
"crypto/subtle",
"crypto/tls",
"crypto/x509",
+\t"crypto/x509/pkix",
+\t"database",
+\t"database/sql",
+\t"database/sql/driver",
+\t"debug",
"debug/dwarf",
-\t"debug/macho",
"debug/elf",
"debug/gosym",
-\t"exp/ebnf",
+\t"debug/macho",
+\t"debug/pe",
+\t"encoding",
"encoding/ascii85",
+\t"encoding/asn1",
+\t"encoding/base32",
"encoding/base64",
"encoding/binary",
+\t"encoding/csv",
+\t"encoding/gob",
"encoding/hex",
+\t"encoding/json",
"encoding/pem",
-\t"os/exec",
+\t"encoding/xml",
+\t"errors",
+\t"expvar",
"flag",
"fmt",
+\t"go",
"go/ast",
+\t"go/build",
"go/doc",
+\t"go/format",
"go/parser",
"go/printer",
"go/scanner",
"go/token",
-\t"encoding/gob",
+\t"go/types",
"hash",
"hash/adler32",
"hash/crc32",
"hash/crc64",
-\t"net/http",
+\t"hash/fnv",
+\t"html",
+\t"html/template",
"image",
+\t"image/color",
+\t"image/draw",
+\t"image/gif",
"image/jpeg",
"image/png",
+\t"index",
+\t"index/suffixarray",
"io",
"io/ioutil",
-\t"encoding/json",
"log",
+\t"log/syslog",
"math",
+\t"math/big",
+\t"math/cmplx",
+\t"math/rand",
"mime",
+\t"mime/multipart",
"net",
+\t"net/http",
+\t"net/http/cgi",
+\t"net/http/cookiejar",
+\t"net/http/fcgi",
+\t"net/http/httptest",
+\t"net/http/httputil",
+\t"net/http/pprof",
+\t"net/mail",
+\t"net/rpc",
+\t"net/rpc/jsonrpc",
+\t"net/smtp",
+\t"net/textproto",
+\t"net/url",
"os",
+\t"os/exec",
+\t"os/signal",
+\t"os/user",
"path",
-\t"math/rand",
+\t"path/filepath",
"reflect",
"regexp",
-\t"net/rpc",
+\t"regexp/syntax",
"runtime",
-\t"text/scanner",
+\t"runtime/cgo",
+\t"runtime/debug",
+\t"runtime/pprof",
+\t"runtime/race",
"sort",
-\t"net/smtp",
"strconv",
"strings",
"sync",
+\t"sync/atomic",
"syscall",
-\t"log/syslog",
-\t"text/tabwriter",
-\t"text/template",
"testing",
"testing/iotest",
"testing/quick",
+\t"text",
+\t"text/scanner",
+\t"text/tabwriter",
+\t"text/template",
+\t"text/template/parse",
"time",
"unicode",
-\t"unicode/utf8",
"unicode/utf16",
-\t"encoding/xml",
+\t"unicode/utf8",
+\t"unsafe",
}
コアとなるコードの解説
このコミットの核心は、parser.go ファイル内の packages というグローバル変数(文字列スライス)の更新です。このスライスは、Goの標準ライブラリに含まれるパッケージのパスを列挙しており、パーサーベンチマークがこれらのパッケージのソースコードを読み込み、解析する対象として使用されます。
変更前は、このリストはGoの標準ライブラリの特定のサブセットのみを含んでおり、時間の経過とともにGoのパッケージ構成が変化したため、古くなっていた可能性があります。
変更後、packages スライスの直前に新しいコメント行が追加されました。
// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
このコメントは、packages スライスがどのように生成されたかを示すシェルコマンドです。このコマンドは以下の処理を行っています。
find . -type d: 現在のディレクトリ(Goリポジトリのルート)からすべてのディレクトリを検索します。-not -path "./exp" -not -path "./exp/*":expディレクトリとそのサブディレクトリを除外します。expは実験的なパッケージや非推奨のパッケージを含むことが多いため、ベンチマークの対象から外すのが適切です。-printf "\t\"%p\",\\n": 見つかった各ディレクトリのパスを、Goのスライス要素として適切な形式(タブ、二重引用符で囲まれたパス、カンマ、改行)で出力します。| sort: 出力されたパスをアルファベット順にソートします。これにより、リストの順序が安定し、差分が最小限に抑えられます。| sed "s/\.\///": パスの先頭にある./を削除します。これにより、"archive/tar"のようなクリーンなパッケージパスが得られます。| grep -v testdata:testdataを含むパスを除外します。testdataディレクトリはテスト用のデータファイルを含むため、実際のパッケージとしては扱われません。
このコマンドによって生成されたリストが、新しい packages スライスの内容となっています。これにより、パーサーベンチマークはGoの標準ライブラリのより広範な範囲をカバーするようになり、Goの進化に合わせてベンチマークの対象が自動的に更新されるメカニズムが導入されたことになります。結果として、パーサーのパフォーマンス測定がより正確で、Goの実際の使用状況を反映したものになります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/
- Go言語の
testingパッケージ: https://pkg.go.dev/testing - Go言語の
go/parserパッケージ: https://pkg.go.dev/go/parser - Go言語のガベージコレクションに関する情報: https://go.dev/doc/gc-guide
参考にした情報源リンク
- Go言語の公式リポジトリ (GitHub): https://github.com/golang/go
- Go Code Review Comments (ベンチマークに関する記述がある可能性): https://go.dev/doc/effective_go#benchmarking
- Go言語の
findコマンドとsed,grepの組み合わせに関する一般的な情報 (シェルスクリプトの知識) - Go言語の
expディレクトリに関する情報 (Goのソースコード構造に関する知識)