diff --git a/test/benchmarks/network/iperf_test.go b/test/benchmarks/network/iperf_test.go index dd3cad61c..55b45a071 100644 --- a/test/benchmarks/network/iperf_test.go +++ b/test/benchmarks/network/iperf_test.go @@ -106,6 +106,170 @@ func BenchmarkIperf(b *testing.B) { } } +func BenchmarkIperfParameterized(b *testing.B) { + clientMachine, err := harness.GetMachine() + if err != nil { + b.Fatalf("failed to get machine: %v", err) + } + defer clientMachine.CleanUp() + + serverMachine, err := harness.GetMachine() + if err != nil { + b.Fatalf("failed to get machine: %v", err) + } + defer serverMachine.CleanUp() + ctx := context.Background() + for _, bm := range []struct { + name string + length int + parallel int + clientFunc func(context.Context, testutil.Logger) *dockerutil.Container + serverFunc func(context.Context, testutil.Logger) *dockerutil.Container + }{ + // We are either measuring the server or the client. The other should be + // runc. e.g. Upload sees how fast the runtime under test uploads to a native + // server. + { + name: "Upload", + length: 4, + parallel: 1, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Upload", + length: 64, + parallel: 1, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Upload", + length: 1024, + parallel: 1, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Upload", + length: 4, + parallel: 16, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Upload", + length: 64, + parallel: 16, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Upload", + length: 1024, + parallel: 16, + clientFunc: clientMachine.GetContainer, + serverFunc: serverMachine.GetNativeContainer, + }, + { + name: "Download", + length: 4, + parallel: 1, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + { + name: "Download", + length: 64, + parallel: 1, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + { + name: "Download", + length: 1024, + parallel: 1, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + { + name: "Download", + length: 4, + parallel: 16, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + { + name: "Download", + length: 64, + parallel: 16, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + { + name: "Download", + length: 1024, + parallel: 16, + clientFunc: clientMachine.GetNativeContainer, + serverFunc: serverMachine.GetContainer, + }, + } { + name, err := tools.ParametersToName(tools.Parameter{ + Name: "operation", + Value: bm.name, + }, tools.Parameter{ + Name: "length", + Value: fmt.Sprintf("%dK", bm.length), + }, tools.Parameter{ + Name: "parallel", + Value: fmt.Sprintf("%d", bm.parallel), + }) + if err != nil { + b.Fatalf("Failed to parse parameters: %v", err) + } + b.Run(name, func(b *testing.B) { + // Set up the containers. + server := bm.serverFunc(ctx, b) + defer server.CleanUp(ctx) + client := bm.clientFunc(ctx, b) + defer client.CleanUp(ctx) + + // iperf serves on port 5001 by default. + port := 5001 + + // Start the server. + if err := server.Spawn(ctx, dockerutil.RunOpts{ + Image: "benchmarks/iperf", + Ports: []int{port}, + }, "iperf", "-s"); err != nil { + b.Fatalf("failed to start server with: %v", err) + } + if out, err := server.WaitForOutput(ctx, fmt.Sprintf("Server listening on TCP port %d", port), 10*time.Second); err != nil { + b.Fatalf("failed to wait for iperf server: %v %s", err, out) + } + + iperf := tools.Iperf{ + Num: b.N, // KB for the client to send. + Length: bm.length, // KB for length. + Parallel: bm.parallel, + } + + // Run the client. + b.ResetTimer() + out, err := client.Run(ctx, dockerutil.RunOpts{ + Image: "benchmarks/iperf", + Links: []string{server.MakeLink("iperfsrv")}, + }, iperf.MakeCmd("iperfsrv", port)...) + if err != nil { + b.Fatalf("failed to run client: %v", err) + } + b.StopTimer() + iperf.Report(b, out) + b.StartTimer() + }) + } +} + func TestMain(m *testing.M) { harness.Init() os.Exit(m.Run()) diff --git a/test/benchmarks/tools/iperf.go b/test/benchmarks/tools/iperf.go index cdd2d0cec..7f873f6b3 100644 --- a/test/benchmarks/tools/iperf.go +++ b/test/benchmarks/tools/iperf.go @@ -21,24 +21,30 @@ import ( "testing" ) -const length = 128 * 1024 - // Iperf is for the client side of `iperf`. type Iperf struct { - Num int // Number of bytes to send in KB. + Num int // Number of bytes to send in KB. + Length int // Length in KB. + Parallel int // Number of parallel threads. } // MakeCmd returns a iperf client command. func (i *Iperf) MakeCmd(host string, port int) []string { - return []string{ - "iperf", - "--format", "K", // Output in KBytes. - "--realtime", // Measured in realtime. - "--num", fmt.Sprintf("%dK", i.Num), // Number of bytes to send in KB. - "--len", fmt.Sprintf("%d", length), - "--client", host, - "--port", fmt.Sprintf("%d", port), + cmd := []string{"iperf"} + cmd = append(cmd, "--format", "K") // Output in KBytes. + cmd = append(cmd, "--realtime") // Measured in realtime. + cmd = append(cmd, "--num", fmt.Sprintf("%dK", i.Num)) // Number of bytes to send in KB. + len := 128 + if i.Length > 0 { + len = i.Length } + cmd = append(cmd, "--len", fmt.Sprintf("%dK", len)) // Length in KB. + cmd = append(cmd, "--client", host) + cmd = append(cmd, "--port", fmt.Sprintf("%d", port)) + if i.Parallel > 0 { + cmd = append(cmd, "--parallel", fmt.Sprintf("%d", i.Parallel)) + } + return cmd } // Report parses output from iperf client and reports metrics. @@ -49,7 +55,7 @@ func (i *Iperf) Report(b *testing.B, output string) { if err != nil { b.Fatalf("failed to parse bandwitdth from %s: %v", output, err) } - b.SetBytes(length) // Measure Bytes/sec for b.N, although below is iperf output. + b.SetBytes(int64(i.Length) * 1024) // Measure Bytes/sec for b.N, although below is iperf output. ReportCustomMetric(b, bW*1024, "bandwidth" /*metric name*/, "bytes_per_second" /*unit*/) }