mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Make all network benchmarks use container links.
This CL uses container links rather than going over the host network stack. This avoids relying on that network stack, making the benchmarks more reliable, and simplifies benchmark setup code. #codehealth PiperOrigin-RevId: 486221868
This commit is contained in:
committed by
gVisor bot
parent
8400a3d40d
commit
5e2f66189c
@@ -17,7 +17,6 @@ package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -48,15 +47,8 @@ func StartServers(ctx context.Context, b *testing.B, args ServerArgs) []*dockeru
|
||||
b.Fatalf("failed to spawn node instance: %v", err)
|
||||
}
|
||||
|
||||
// Get the container IP.
|
||||
servingIP, err := server.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
CleanUpContainers(ctx, servers)
|
||||
b.Fatalf("failed to get ip from server: %v", err)
|
||||
}
|
||||
|
||||
// Wait until the server is up.
|
||||
if err := harness.WaitUntilServing(ctx, args.Machine, servingIP, args.Port); err != nil {
|
||||
if err := harness.WaitUntilContainerServing(ctx, args.Machine, server, args.Port); err != nil {
|
||||
CleanUpContainers(ctx, servers)
|
||||
b.Fatalf("failed to wait for serving")
|
||||
}
|
||||
@@ -74,7 +66,7 @@ func CleanUpContainers(ctx context.Context, containers []*dockerutil.Container)
|
||||
}
|
||||
|
||||
// RedisInstance returns a Redis container and its reachable IP.
|
||||
func RedisInstance(ctx context.Context, b *testing.B, machine harness.Machine) (*dockerutil.Container, net.IP) {
|
||||
func RedisInstance(ctx context.Context, b *testing.B, machine harness.Machine) *dockerutil.Container {
|
||||
b.Helper()
|
||||
// Spawn a redis instance for the app to use.
|
||||
redis := machine.GetNativeContainer(ctx, b)
|
||||
@@ -89,10 +81,5 @@ func RedisInstance(ctx context.Context, b *testing.B, machine harness.Machine) (
|
||||
redis.CleanUp(ctx)
|
||||
b.Fatalf("failed to start redis server: %v %s", err, out)
|
||||
}
|
||||
redisIP, err := redis.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
redis.CleanUp(ctx)
|
||||
b.Fatalf("failed to get IP from redis instance: %v", err)
|
||||
}
|
||||
return redis, redisIP
|
||||
return redis
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func BenchmarkSizeNode(b *testing.B) {
|
||||
|
||||
// Make a redis instance for Node to connect.
|
||||
ctx := context.Background()
|
||||
redis, redisIP := base.RedisInstance(ctx, b, machine)
|
||||
redis := base.RedisInstance(ctx, b, machine)
|
||||
defer redis.CleanUp(ctx)
|
||||
|
||||
// DropCaches after redis is created.
|
||||
@@ -152,7 +152,7 @@ func BenchmarkSizeNode(b *testing.B) {
|
||||
WorkDir: "/usr/src/app",
|
||||
Links: []string{redis.MakeLink("redis")},
|
||||
}
|
||||
nodeCmd := []string{"node", "index.js", redisIP.String()}
|
||||
nodeCmd := []string{"node", "index.js", "redis"}
|
||||
const port = 8080
|
||||
servers := base.StartServers(ctx, b,
|
||||
base.ServerArgs{
|
||||
|
||||
@@ -85,7 +85,7 @@ func BenchmarkStartupNode(b *testing.B) {
|
||||
defer machine.CleanUp()
|
||||
|
||||
ctx := context.Background()
|
||||
redis, redisIP := base.RedisInstance(ctx, b, machine)
|
||||
redis := base.RedisInstance(ctx, b, machine)
|
||||
defer redis.CleanUp(ctx)
|
||||
runOpts := dockerutil.RunOpts{
|
||||
Image: "benchmarks/node",
|
||||
@@ -93,7 +93,7 @@ func BenchmarkStartupNode(b *testing.B) {
|
||||
Links: []string{redis.MakeLink("redis")},
|
||||
}
|
||||
|
||||
cmd := []string{"node", "index.js", redisIP.String()}
|
||||
cmd := []string{"node", "index.js", "redis"}
|
||||
runServerWorkload(ctx, b,
|
||||
base.ServerArgs{
|
||||
Machine: machine,
|
||||
@@ -122,15 +122,9 @@ func runServerWorkload(ctx context.Context, b *testing.B, args base.ServerArgs)
|
||||
return fmt.Errorf("failed to spawn node instance: %v", err)
|
||||
}
|
||||
|
||||
harness.DebugLog(b, "Finding Container IP")
|
||||
servingIP, err := server.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get ip from server: %v", err)
|
||||
}
|
||||
|
||||
// Wait until the Client sees the server as up.
|
||||
harness.DebugLog(b, "Waiting for container to start.")
|
||||
if err := harness.WaitUntilServing(ctx, args.Machine, servingIP, args.Port); err != nil {
|
||||
if err := harness.WaitUntilContainerServing(ctx, args.Machine, server, args.Port); err != nil {
|
||||
return fmt.Errorf("failed to wait for serving: %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -81,17 +81,7 @@ func BenchmarkRedis(b *testing.B) {
|
||||
b.Fatalf("failed to start redis server: %v %s", err, out)
|
||||
}
|
||||
|
||||
ip, err := serverMachine.IPAddress()
|
||||
if err != nil {
|
||||
b.Fatalf("failed to get IP from server: %v", err)
|
||||
}
|
||||
|
||||
serverPort, err := server.FindPort(ctx, port)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to get IP from server: %v", err)
|
||||
}
|
||||
|
||||
if err = harness.WaitUntilServing(ctx, clientMachine, ip, serverPort); err != nil {
|
||||
if err = harness.WaitUntilContainerServing(ctx, clientMachine, server, port); err != nil {
|
||||
b.Fatalf("failed to start redis with: %v", err)
|
||||
}
|
||||
for _, operation := range operations {
|
||||
@@ -120,7 +110,8 @@ func BenchmarkRedis(b *testing.B) {
|
||||
|
||||
out, err = client.Run(ctx, dockerutil.RunOpts{
|
||||
Image: "benchmarks/redis",
|
||||
}, redis.MakeCmd(ip, serverPort, b.N /*requests*/)...)
|
||||
Links: []string{server.MakeLink("redis")},
|
||||
}, redis.MakeCmd("redis", port, b.N /*requests*/)...)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -17,7 +17,6 @@ package harness
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -29,16 +28,17 @@ import (
|
||||
|
||||
//TODO(gvisor.dev/issue/3535): move to own package or move methods to harness struct.
|
||||
|
||||
// WaitUntilServing grabs a container from `machine` and waits for a server at
|
||||
// IP:port.
|
||||
func WaitUntilServing(ctx context.Context, machine Machine, server net.IP, port int) error {
|
||||
// WaitUntilContainerServing grabs a container from `machine` and waits for a server on
|
||||
// the given container and port.
|
||||
func WaitUntilContainerServing(ctx context.Context, machine Machine, container *dockerutil.Container, port int) error {
|
||||
var logger testutil.DefaultLogger = "util"
|
||||
netcat := machine.GetNativeContainer(ctx, logger)
|
||||
defer netcat.CleanUp(ctx)
|
||||
|
||||
cmd := fmt.Sprintf("while ! wget -q --spider http://%s:%d; do true; done", server, port)
|
||||
cmd := fmt.Sprintf("while ! wget -q --spider http://%s:%d; do true; done", "server", port)
|
||||
_, err := netcat.Run(ctx, dockerutil.RunOpts{
|
||||
Image: "benchmarks/util",
|
||||
Links: []string{container.MakeLink("server")},
|
||||
}, "sh", "-c", cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,26 +52,15 @@ func runStaticServer(b *testing.B, serverOpts dockerutil.RunOpts, serverCmd []st
|
||||
b.Fatalf("failed to start server: %v", err)
|
||||
}
|
||||
|
||||
// Get its IP.
|
||||
ip, err := serverMachine.IPAddress()
|
||||
if err != nil {
|
||||
b.Fatalf("failed to find server ip: %v", err)
|
||||
}
|
||||
|
||||
// Get the published port.
|
||||
servingPort, err := server.FindPort(ctx, port)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to find server port %d: %v", port, err)
|
||||
}
|
||||
|
||||
// Make sure the server is serving.
|
||||
harness.WaitUntilServing(ctx, clientMachine, ip, servingPort)
|
||||
harness.WaitUntilContainerServing(ctx, clientMachine, server, port)
|
||||
|
||||
// Run the client.
|
||||
b.ResetTimer()
|
||||
out, err := client.Run(ctx, dockerutil.RunOpts{
|
||||
Image: "benchmarks/hey",
|
||||
}, hey.MakeCmd(ip, servingPort)...)
|
||||
Links: []string{server.MakeLink("server")},
|
||||
}, hey.MakeCmd("server", port)...)
|
||||
if err != nil {
|
||||
b.Fatalf("run failed with: %v", err)
|
||||
}
|
||||
|
||||
@@ -102,26 +102,17 @@ func runNode(b *testing.B, hey *tools.Hey) {
|
||||
}
|
||||
defer nodeApp.CleanUp(ctx)
|
||||
|
||||
servingIP, err := serverMachine.IPAddress()
|
||||
if err != nil {
|
||||
b.Fatalf("failed to get ip from server: %v", err)
|
||||
}
|
||||
|
||||
servingPort, err := nodeApp.FindPort(ctx, port)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to port from node instance: %v", err)
|
||||
}
|
||||
|
||||
// Wait until the Client sees the server as up.
|
||||
harness.WaitUntilServing(ctx, clientMachine, servingIP, servingPort)
|
||||
harness.WaitUntilContainerServing(ctx, clientMachine, nodeApp, port)
|
||||
|
||||
heyCmd := hey.MakeCmd(servingIP, servingPort)
|
||||
heyCmd := hey.MakeCmd("node", port)
|
||||
|
||||
// the client should run on Native.
|
||||
b.ResetTimer()
|
||||
client := clientMachine.GetNativeContainer(ctx, b)
|
||||
out, err := client.Run(ctx, dockerutil.RunOpts{
|
||||
Image: "benchmarks/hey",
|
||||
Links: []string{nodeApp.MakeLink("node")},
|
||||
}, heyCmd...)
|
||||
if err != nil {
|
||||
b.Fatalf("hey container failed: %v logs: %s", err, out)
|
||||
|
||||
@@ -80,10 +80,6 @@ func runRuby(b *testing.B, hey *tools.Hey) {
|
||||
if out, err := redis.WaitForOutput(ctx, "Ready to accept connections", 3*time.Second); err != nil {
|
||||
b.Fatalf("failed to start redis server: %v %s", err, out)
|
||||
}
|
||||
redisIP, err := redis.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to get IP from redis instance: %v", err)
|
||||
}
|
||||
|
||||
// Ruby runs on port 9292.
|
||||
const port = 9292
|
||||
@@ -100,7 +96,7 @@ func runRuby(b *testing.B, hey *tools.Hey) {
|
||||
"WEB_CONCURRENCY=20",
|
||||
"WEB_MAX_THREADS=20",
|
||||
"RACK_ENV=production",
|
||||
fmt.Sprintf("HOST=%s", redisIP),
|
||||
"HOST=redis",
|
||||
},
|
||||
User: "nobody",
|
||||
}, "sh", "-c", "/usr/bin/puma"); err != nil {
|
||||
@@ -108,21 +104,11 @@ func runRuby(b *testing.B, hey *tools.Hey) {
|
||||
}
|
||||
defer rubyApp.CleanUp(ctx)
|
||||
|
||||
servingIP, err := serverMachine.IPAddress()
|
||||
if err != nil {
|
||||
b.Fatalf("failed to get ip from server: %v", err)
|
||||
}
|
||||
|
||||
servingPort, err := rubyApp.FindPort(ctx, port)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to port from node instance: %v", err)
|
||||
}
|
||||
|
||||
// Wait until the Client sees the server as up.
|
||||
if err := harness.WaitUntilServing(ctx, clientMachine, servingIP, servingPort); err != nil {
|
||||
if err := harness.WaitUntilContainerServing(ctx, clientMachine, rubyApp, port); err != nil {
|
||||
b.Fatalf("failed to wait until serving: %v", err)
|
||||
}
|
||||
heyCmd := hey.MakeCmd(servingIP, servingPort)
|
||||
heyCmd := hey.MakeCmd("ruby", port)
|
||||
|
||||
// the client should run on Native.
|
||||
b.ResetTimer()
|
||||
@@ -130,6 +116,7 @@ func runRuby(b *testing.B, hey *tools.Hey) {
|
||||
defer client.CleanUp(ctx)
|
||||
out, err := client.Run(ctx, dockerutil.RunOpts{
|
||||
Image: "benchmarks/hey",
|
||||
Links: []string{rubyApp.MakeLink("ruby")},
|
||||
}, heyCmd...)
|
||||
if err != nil {
|
||||
b.Fatalf("hey container failed: %v logs: %s", err, out)
|
||||
|
||||
@@ -16,7 +16,6 @@ package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -31,8 +30,8 @@ type ApacheBench struct {
|
||||
}
|
||||
|
||||
// MakeCmd makes an ApacheBench command.
|
||||
func (a *ApacheBench) MakeCmd(ip net.IP, port int) []string {
|
||||
path := fmt.Sprintf("http://%s:%d/%s", ip, port, a.Doc)
|
||||
func (a *ApacheBench) MakeCmd(host string, port int) []string {
|
||||
path := fmt.Sprintf("http://%s:%d/%s", host, port, a.Doc)
|
||||
// See apachebench (ab) for flags.
|
||||
cmd := fmt.Sprintf("ab -n %d -c %d %s", a.Requests, a.Concurrency, path)
|
||||
return []string{"sh", "-c", cmd}
|
||||
|
||||
@@ -16,7 +16,6 @@ package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -30,7 +29,7 @@ type Hey struct {
|
||||
}
|
||||
|
||||
// MakeCmd returns a 'hey' command.
|
||||
func (h *Hey) MakeCmd(ip net.IP, port int) []string {
|
||||
func (h *Hey) MakeCmd(host string, port int) []string {
|
||||
c := h.Concurrency
|
||||
if c > h.Requests {
|
||||
c = h.Requests
|
||||
@@ -39,7 +38,7 @@ func (h *Hey) MakeCmd(ip net.IP, port int) []string {
|
||||
"hey",
|
||||
"-n", fmt.Sprintf("%d", h.Requests),
|
||||
"-c", fmt.Sprintf("%d", c),
|
||||
fmt.Sprintf("http://%s:%d/%s", ip.String(), port, h.Doc),
|
||||
fmt.Sprintf("http://%s:%d/%s", host, port, h.Doc),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -28,7 +27,7 @@ type Redis struct {
|
||||
}
|
||||
|
||||
// MakeCmd returns a redis-benchmark client command.
|
||||
func (r *Redis) MakeCmd(ip net.IP, port, requests int) []string {
|
||||
func (r *Redis) MakeCmd(host string, port, requests int) []string {
|
||||
// There is no -t PING_BULK for redis-benchmark, so adjust the command in that case.
|
||||
// Note that "ping" will run both PING_INLINE and PING_BULK.
|
||||
if r.Operation == "PING_BULK" {
|
||||
@@ -36,7 +35,7 @@ func (r *Redis) MakeCmd(ip net.IP, port, requests int) []string {
|
||||
"redis-benchmark",
|
||||
"--csv",
|
||||
"-t", "ping",
|
||||
"-h", ip.String(),
|
||||
"-h", host,
|
||||
"-p", fmt.Sprintf("%d", port),
|
||||
"-n", fmt.Sprintf("%d", requests),
|
||||
}
|
||||
@@ -47,7 +46,7 @@ func (r *Redis) MakeCmd(ip net.IP, port, requests int) []string {
|
||||
"redis-benchmark",
|
||||
"--csv",
|
||||
"-t", r.Operation,
|
||||
"-h", ip.String(),
|
||||
"-h", host,
|
||||
"-p", fmt.Sprintf("%d", port),
|
||||
"-n", fmt.Sprintf("%d", requests),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user