[インデックス 15562] ファイルの概要
このコミットは、Go言語の標準ライブラリである net
パッケージにおいて、TCP通信のベンチマークテストにIPv6のサポートを追加するものです。具体的には、既存のTCPベンチマーク関数を拡張し、IPv4だけでなくIPv6アドレスに対してもベンチマークを実行できるように変更されています。これにより、GoのネットワークスタックがIPv6環境下でどのようにパフォーマンスを発揮するかを測定・評価できるようになります。
コミット
net: add TCP over IPv6 benchmarks
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/13393fb6c7bf78a61ea3f44753396687abe2c5b5
元コミット内容
net: add TCP over IPv6 benchmarks
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/7433044
変更の背景
この変更の背景には、ネットワーク技術におけるIPv6の普及と重要性の高まりがあります。IPv4アドレスの枯渇問題が顕在化する中で、IPv6は次世代のインターネットプロトコルとして広く採用されつつあります。Go言語のようなモダンなプログラミング言語のネットワークライブラリは、IPv4とIPv6の両方を効率的かつ堅牢にサポートすることが求められます。
既存のTCPベンチマークはIPv4に限定されており、IPv6環境下でのGoのネットワークパフォーマンスを測定する手段がありませんでした。このコミットは、IPv6環境でのTCP通信の性能特性を把握し、潜在的なボトルネックや最適化の機会を特定するために、IPv6対応のベンチマークを追加することを目的としています。これにより、Goの net
パッケージがIPv6環境でも期待通りの性能を発揮することを確認し、必要に応じて改善を行うための基盤が提供されます。
前提知識の解説
TCP (Transmission Control Protocol)
TCPは、インターネットプロトコルスイートの主要なプロトコルの一つで、信頼性の高い、コネクション指向のデータ転送サービスを提供します。アプリケーション層のデータがネットワークを介して正確かつ順序通りに配信されることを保証します。ストリーミングデータ、ファイル転送、ウェブブラウジングなど、多くのインターネットアプリケーションで利用されています。
IPv4 (Internet Protocol version 4)
IPv4は、インターネット上でデバイスを識別し、ルーティングを行うためのプロトコルです。32ビットのアドレスを使用し、約43億個の一意なアドレスを割り当てることができます。しかし、インターネットの急速な普及により、このアドレス空間はほぼ枯渇しています。
IPv6 (Internet Protocol version 6)
IPv6は、IPv4の後継として開発されたインターネットプロトコルです。128ビットのアドレスを使用するため、膨大な数のアドレス(約3.4×10^38個)を割り当てることができ、アドレス枯渇問題を解決します。また、IPv4と比較して、ルーティングの効率化、セキュリティ機能の強化(IPsecの内蔵)、モバイルIPのサポートなど、いくつかの改善が加えられています。IPv6アドレスは通常、:
で区切られた16進数のグループで表現され、ループバックアドレスは ::1
です。
Go言語の net
パッケージ
Go言語の標準ライブラリ net
パッケージは、ネットワークI/Oのプリミティブを提供します。TCP/IP、UDP、IP、Unixドメインソケットなどのネットワークプロトコルをサポートし、クライアントとサーバーアプリケーションの構築を容易にします。net.Listen
関数は、指定されたネットワークアドレスで着信接続をリッスンするために使用されます。
Go言語の testing
パッケージとベンチマーク
Go言語の testing
パッケージは、ユニットテストとベンチマークテストの両方をサポートします。ベンチマークテストは、関数のパフォーマンスを測定するために使用され、BenchmarkXxx
という命名規則に従います。*testing.B
型の引数を受け取り、b.N
回の操作を実行します。b.Skip
メソッドは、特定の条件が満たされない場合にベンチマークをスキップするために使用されます。
技術的詳細
このコミットは、src/pkg/net/tcp_test.go
ファイル内のTCPベンチマークテストを拡張し、IPv6のサポートを追加しています。主な変更点は以下の通りです。
-
benchmarkTCP
関数のシグネチャ変更: 既存のbenchmarkTCP
関数は、func benchmarkTCP(b *testing.B, persistent, timeout bool)
でしたが、これにladdr string
という新しい引数が追加され、func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string)
となりました。このladdr
引数によって、ベンチマークで使用するローカルアドレス(IPv4またはIPv6)を動的に指定できるようになります。 -
IPv6ベンチマーク関数の追加:
BenchmarkTCPOneShot
、BenchmarkTCPOneShotTimeout
、BenchmarkTCPPersistent
、BenchmarkTCPPersistentTimeout
といった既存のIPv4ベンチマークに対応する形で、IPv6用の新しいベンチマーク関数が追加されました。これらはそれぞれBenchmarkTCP6OneShot
、BenchmarkTCP6OneShotTimeout
、BenchmarkTCP6Persistent
、BenchmarkTCP6PersistentTimeout
と命名されています。 -
IPv6アドレスの指定: 新しく追加されたIPv6ベンチマーク関数では、
benchmarkTCP
関数を呼び出す際に、IPv6のループバックアドレス[::1]:0
をladdr
引数として渡しています。[::1]
はIPv6のループバックアドレスであり、:0
は利用可能な任意のポートを意味します。 -
IPv6サポートのチェック: IPv6ベンチマーク関数は、
supportsIPv6
というグローバル変数(または同様のメカニズム)をチェックし、システムがIPv6をサポートしていない場合はb.Skip("ipv6 is not supported")
を呼び出してベンチマークをスキップします。これにより、IPv6が利用できない環境でテストが失敗するのを防ぎます。 -
net.Listen
のアドレス変更:benchmarkTCP
関数内で、net.Listen("tcp", "127.0.0.1:0")
とハードコードされていた部分が、新しいladdr
引数を使用するようにnet.Listen("tcp", laddr)
に変更されました。これにより、IPv4 (127.0.0.1:0
) とIPv6 ([::1]:0
) の両方でリスナーを作成できるようになります。
これらの変更により、GoのネットワークスタックがIPv6環境下でどのように動作し、どの程度のパフォーマンスを発揮するかを、既存のベンチマークフレームワーク内で測定できるようになりました。
コアとなるコードの変更箇所
変更は src/pkg/net/tcp_test.go
ファイルに集中しています。
--- a/src/pkg/net/tcp_test.go
+++ b/src/pkg/net/tcp_test.go
@@ -11,23 +11,51 @@ import (
"time"
)
-func BenchmarkTCPOneShot(b *testing.B) {
- benchmarkTCP(b, false, false)
+func BenchmarkTCP4OneShot(b *testing.B) {
+ benchmarkTCP(b, false, false, "127.0.0.1:0")
}
-func BenchmarkTCPOneShotTimeout(b *testing.B) {
- benchmarkTCP(b, false, true)
+func BenchmarkTCP4OneShotTimeout(b *testing.B) {
+ benchmarkTCP(b, false, true, "127.0.0.1:0")
}
-func BenchmarkTCPPersistent(b *testing.B) {
- benchmarkTCP(b, true, false)
+func BenchmarkTCP4Persistent(b *testing.B) {
+ benchmarkTCP(b, true, false, "127.0.0.1:0")
}
-func BenchmarkTCPPersistentTimeout(b *testing.B) {
- benchmarkTCP(b, true, true)
+func BenchmarkTCP4PersistentTimeout(b *testing.B) {
+ benchmarkTCP(b, true, true, "127.0.0.1:0")
}
-func benchmarkTCP(b *testing.B, persistent, timeout bool) {
+func BenchmarkTCP6OneShot(b *testing.B) {
+ if !supportsIPv6 {
+ b.Skip("ipv6 is not supported")
+ }
+ benchmarkTCP(b, false, false, "[::1]:0")
+}
+
+func BenchmarkTCP6OneShotTimeout(b *testing.B) {
+ if !supportsIPv6 {
+ b.Skip("ipv6 is not supported")
+ }
+ benchmarkTCP(b, false, true, "[::1]:0")
+}
+
+func BenchmarkTCP6Persistent(b *testing.B) {
+ if !supportsIPv6 {
+ b.Skip("ipv6 is not supported")
+ }
+ benchmarkTCP(b, true, false, "[::1]:0")
+}
+
+func BenchmarkTCP6PersistentTimeout(b *testing.B) {
+ if !supportsIPv6 {
+ b.Skip("ipv6 is not supported")
+ }
+ benchmarkTCP(b, true, true, "[::1]:0")
+}
+
+func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
const msgLen = 512
conns := b.N
numConcurrent := runtime.GOMAXPROCS(-1) * 16
@@ -61,7 +89,7 @@ func benchmarkTCP(b *testing.B, persistent, timeout bool) {
}
return true
}
- ln, err := Listen("tcp", "127.0.0.1:0")
+ ln, err := Listen("tcp", laddr)
if err != nil {
b.Fatalf("Listen failed: %v", err)
}
コアとなるコードの解説
benchmarkTCP
関数の変更
元の benchmarkTCP
関数は、TCPベンチマークの共通ロジックをカプセル化していました。このコミットでは、この関数のシグネチャが以下のように変更されました。
func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
// ...
ln, err := Listen("tcp", laddr) // 変更点
// ...
}
新しい laddr string
引数は、リスニングするネットワークアドレスを指定するために使用されます。これにより、benchmarkTCP
関数はIPv4 ("127.0.0.1:0"
) とIPv6 ("[::1]:0"
) の両方のアドレスでリスナーを作成できるようになり、コードの再利用性が向上しました。
新しいIPv6ベンチマーク関数
IPv6ベンチマーク関数は、既存のIPv4ベンチマーク関数とほぼ同じ構造を持っていますが、benchmarkTCP
を呼び出す際にIPv6のループバックアドレス [::1]:0
を渡します。
例: BenchmarkTCP6OneShot
func BenchmarkTCP6OneShot(b *testing.B) {
if !supportsIPv6 { // IPv6サポートのチェック
b.Skip("ipv6 is not supported")
}
benchmarkTCP(b, false, false, "[::1]:0") // IPv6アドレスを指定
}
supportsIPv6
の利用
supportsIPv6
は、Goの net
パッケージのテストスイート内で定義されている変数で、現在のシステムがIPv6をサポートしているかどうかを示すブール値です。IPv6ベンチマーク関数は、この supportsIPv6
の値を確認し、false
の場合は b.Skip
を呼び出してベンチマークをスキップします。これは、IPv6が有効になっていない環境でベンチマークを実行しようとした場合に、テストが失敗するのではなく、適切にスキップされるようにするための重要なガードです。これにより、テストの堅牢性と移植性が向上します。
これらの変更により、Goの net
パッケージは、IPv4とIPv6の両方でTCP通信のパフォーマンスを測定するための包括的なベンチマークスイートを持つことになります。
関連リンク
- Go Code Review: https://golang.org/cl/7433044
参考にした情報源リンク
- Go言語
net
パッケージ公式ドキュメント: https://pkg.go.dev/net - Go言語
testing
パッケージ公式ドキュメント: https://pkg.go.dev/testing - TCP/IPに関する一般的な情報 (例: Wikipedia)
- IPv4とIPv6に関する一般的な情報 (例: Wikipedia)
- Go言語のベンチマークに関する記事やチュートリアル (例: Go公式ブログ、各種技術ブログ)