diff options
author | Zach Koopmans <zkoopmans@google.com> | 2020-09-02 11:20:45 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-09-02 11:22:17 -0700 |
commit | b9b6660dc4ec0cee77bb30ac7a44c061ada1b3d6 (patch) | |
tree | fee986153a27c8cbef8002dc808fc8e4dc21b965 | |
parent | 8ab08cdc01e2e4b36a050ffc3acad682aebaa7b5 (diff) |
Add Docs to nginx benchmark.
Adds docs to nginx and refactors both Httpd and Nginx benchmarks.
Key changes:
- Add docs and make nginx tests the same as httpd (reverse, all docs, etc.).
- Make requests scale on c * b.N -> a request per thread. This works well
with both --test.benchtime=10m (do a run that lasts at least 10m) and
--test.benchtime=10x (do b.N = 10).
-- Remove a doc from both tests (1000Kb) as 1024Kb exists.
PiperOrigin-RevId: 329751091
-rw-r--r-- | images/benchmarks/httpd/Dockerfile | 2 | ||||
-rw-r--r-- | images/benchmarks/nginx/Dockerfile | 10 | ||||
-rw-r--r-- | images/benchmarks/nginx/nginx.conf | 19 | ||||
-rw-r--r-- | test/benchmarks/network/BUILD | 11 | ||||
-rw-r--r-- | test/benchmarks/network/httpd_test.go | 110 | ||||
-rw-r--r-- | test/benchmarks/network/nginx_test.go | 113 | ||||
-rw-r--r-- | test/benchmarks/network/static_server.go | 88 |
7 files changed, 193 insertions, 160 deletions
diff --git a/images/benchmarks/httpd/Dockerfile b/images/benchmarks/httpd/Dockerfile index b72406012..e95538a40 100644 --- a/images/benchmarks/httpd/Dockerfile +++ b/images/benchmarks/httpd/Dockerfile @@ -8,7 +8,7 @@ RUN set -x \ # Generate a bunch of relevant files. RUN mkdir -p /local && \ - for size in 1 10 100 1000 1024 10240; do \ + for size in 1 10 100 1024 10240; do \ dd if=/dev/zero of=/local/latin${size}k.txt count=${size} bs=1024; \ done diff --git a/images/benchmarks/nginx/Dockerfile b/images/benchmarks/nginx/Dockerfile index b64eb52ae..2444d04b1 100644 --- a/images/benchmarks/nginx/Dockerfile +++ b/images/benchmarks/nginx/Dockerfile @@ -1 +1,11 @@ FROM nginx:1.15.10 + +# Generate a bunch of relevant files. +RUN mkdir -p /local && \ + for size in 1 10 100 1024 10240; do \ + dd if=/dev/zero of=/local/latin${size}k.txt count=${size} bs=1024; \ + done + +RUN touch /local/index.html + +COPY ./nginx.conf /etc/nginx/nginx.conf diff --git a/images/benchmarks/nginx/nginx.conf b/images/benchmarks/nginx/nginx.conf new file mode 100644 index 000000000..2c43c0cda --- /dev/null +++ b/images/benchmarks/nginx/nginx.conf @@ -0,0 +1,19 @@ +user nginx; +worker_processes 1; +daemon off; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + + +http { + server { + location / { + root /tmp/html; + } + } +} diff --git a/test/benchmarks/network/BUILD b/test/benchmarks/network/BUILD index bd3f6245c..472b5c387 100644 --- a/test/benchmarks/network/BUILD +++ b/test/benchmarks/network/BUILD @@ -5,8 +5,15 @@ package(licenses = ["notice"]) go_library( name = "network", testonly = 1, - srcs = ["network.go"], - deps = ["//test/benchmarks/harness"], + srcs = [ + "network.go", + "static_server.go", + ], + deps = [ + "//pkg/test/dockerutil", + "//test/benchmarks/harness", + "//test/benchmarks/tools", + ], ) go_test( diff --git a/test/benchmarks/network/httpd_test.go b/test/benchmarks/network/httpd_test.go index 336e04c91..369ab326e 100644 --- a/test/benchmarks/network/httpd_test.go +++ b/test/benchmarks/network/httpd_test.go @@ -14,22 +14,19 @@ package network import ( - "context" "fmt" "testing" "gvisor.dev/gvisor/pkg/test/dockerutil" - "gvisor.dev/gvisor/test/benchmarks/harness" "gvisor.dev/gvisor/test/benchmarks/tools" ) // see Dockerfile '//images/benchmarks/httpd'. -var docs = map[string]string{ +var httpdDocs = map[string]string{ "notfound": "notfound", "1Kb": "latin1k.txt", "10Kb": "latin10k.txt", "100Kb": "latin100k.txt", - "1000Kb": "latin1000k.txt", "1Mb": "latin1024k.txt", "10Mb": "latin10240k.txt", } @@ -37,30 +34,17 @@ var docs = map[string]string{ // BenchmarkHttpdConcurrency iterates the concurrency argument and tests // how well the runtime under test handles requests in parallel. func BenchmarkHttpdConcurrency(b *testing.B) { - // Grab a machine for the client and server. - clientMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get client: %v", err) - } - defer clientMachine.CleanUp() - - serverMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get server: %v", err) - } - defer serverMachine.CleanUp() - // The test iterates over client concurrency, so set other parameters. concurrency := []int{1, 25, 50, 100, 1000} for _, c := range concurrency { b.Run(fmt.Sprintf("%d", c), func(b *testing.B) { hey := &tools.Hey{ - Requests: 10000, + Requests: c * b.N, Concurrency: c, - Doc: docs["10Kb"], + Doc: httpdDocs["10Kb"], } - runHttpd(b, clientMachine, serverMachine, hey, false /* reverse */) + runHttpd(b, hey, false /* reverse */) }) } } @@ -77,57 +61,30 @@ func BenchmarkReverseHttpdDocSize(b *testing.B) { benchmarkHttpdDocSize(b, true /* reverse */) } +// benchmarkHttpdDocSize iterates through all doc sizes, running subbenchmarks +// for each size. func benchmarkHttpdDocSize(b *testing.B, reverse bool) { b.Helper() - - clientMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get machine: %v", err) - } - defer clientMachine.CleanUp() - - serverMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get machine: %v", err) - } - defer serverMachine.CleanUp() - - for name, filename := range docs { + for name, filename := range httpdDocs { concurrency := []int{1, 25, 50, 100, 1000} for _, c := range concurrency { b.Run(fmt.Sprintf("%s_%d", name, c), func(b *testing.B) { hey := &tools.Hey{ - Requests: 10000, + Requests: c * b.N, Concurrency: c, Doc: filename, } - runHttpd(b, clientMachine, serverMachine, hey, reverse) + runHttpd(b, hey, reverse) }) } } } -// runHttpd runs a single test run. -func runHttpd(b *testing.B, clientMachine, serverMachine harness.Machine, hey *tools.Hey, reverse bool) { - b.Helper() - - // Grab a container from the server. - ctx := context.Background() - var server *dockerutil.Container - if reverse { - server = serverMachine.GetNativeContainer(ctx, b) - } else { - server = serverMachine.GetContainer(ctx, b) - } - - defer server.CleanUp(ctx) - - // Copy the docs to /tmp and serve from there. - cmd := "mkdir -p /tmp/html; cp -r /local/* /tmp/html/.; apache2 -X" +// runHttpd configures the static serving methods to run httpd. +func runHttpd(b *testing.B, hey *tools.Hey, reverse bool) { + // httpd runs on port 80. port := 80 - - // Start the server. - if err := server.Spawn(ctx, dockerutil.RunOpts{ + httpdRunOpts := dockerutil.RunOpts{ Image: "benchmarks/httpd", Ports: []int{port}, Env: []string{ @@ -138,44 +95,7 @@ func runHttpd(b *testing.B, clientMachine, serverMachine harness.Machine, hey *t "APACHE_LOG_DIR=/tmp", "APACHE_PID_FILE=/tmp/apache.pid", }, - }, "sh", "-c", cmd); err != nil { - b.Fatalf("failed to start server: %v", err) - } - - ip, err := serverMachine.IPAddress() - if err != nil { - b.Fatalf("failed to find server ip: %v", err) - } - - servingPort, err := server.FindPort(ctx, port) - if err != nil { - b.Fatalf("failed to find server port %d: %v", port, err) - } - - // Check the server is serving. - harness.WaitUntilServing(ctx, clientMachine, ip, servingPort) - - var client *dockerutil.Container - // Grab a client. - if reverse { - client = clientMachine.GetContainer(ctx, b) - } else { - client = clientMachine.GetNativeContainer(ctx, b) - } - defer client.CleanUp(ctx) - - b.ResetTimer() - server.RestartProfiles() - for i := 0; i < b.N; i++ { - out, err := client.Run(ctx, dockerutil.RunOpts{ - Image: "benchmarks/hey", - }, hey.MakeCmd(ip, servingPort)...) - if err != nil { - b.Fatalf("run failed with: %v", err) - } - - b.StopTimer() - hey.Report(b, out) - b.StartTimer() } + httpdCmd := []string{"sh", "-c", "mkdir -p /tmp/html; cp -r /local/* /tmp/html/.; apache2 -X"} + runStaticServer(b, httpdRunOpts, httpdCmd, port, hey, reverse) } diff --git a/test/benchmarks/network/nginx_test.go b/test/benchmarks/network/nginx_test.go index 2bf1a3624..036fd666f 100644 --- a/test/benchmarks/network/nginx_test.go +++ b/test/benchmarks/network/nginx_test.go @@ -14,91 +14,80 @@ package network import ( - "context" "fmt" "testing" "gvisor.dev/gvisor/pkg/test/dockerutil" - "gvisor.dev/gvisor/test/benchmarks/harness" "gvisor.dev/gvisor/test/benchmarks/tools" ) +// see Dockerfile '//images/benchmarks/nginx'. +var nginxDocs = map[string]string{ + "notfound": "notfound", + "1Kb": "latin1k.txt", + "10Kb": "latin10k.txt", + "100Kb": "latin100k.txt", + "1Mb": "latin1024k.txt", + "10Mb": "latin10240k.txt", +} + // BenchmarkNginxConcurrency iterates the concurrency argument and tests // how well the runtime under test handles requests in parallel. -// TODO(gvisor.dev/issue/3536): Update with different doc sizes like Httpd. func BenchmarkNginxConcurrency(b *testing.B) { - // Grab a machine for the client and server. - clientMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get client: %v", err) - } - defer clientMachine.CleanUp() - - serverMachine, err := h.GetMachine() - if err != nil { - b.Fatalf("failed to get server: %v", err) - } - defer serverMachine.CleanUp() - - concurrency := []int{1, 5, 10, 25} + concurrency := []int{1, 25, 100, 1000} for _, c := range concurrency { b.Run(fmt.Sprintf("%d", c), func(b *testing.B) { hey := &tools.Hey{ - Requests: 10000, + Requests: c * b.N, Concurrency: c, + Doc: nginxDocs["10kb"], // see Dockerfile '//images/benchmarks/nginx' and httpd_test. } - runNginx(b, clientMachine, serverMachine, hey) + runNginx(b, hey, false /* reverse */) }) } } -// runHttpd runs a single test run. -func runNginx(b *testing.B, clientMachine, serverMachine harness.Machine, hey *tools.Hey) { - b.Helper() - - // Grab a container from the server. - ctx := context.Background() - server := serverMachine.GetContainer(ctx, b) - defer server.CleanUp(ctx) +// BenchmarkNginxDocSize iterates over different sized payloads, testing how +// well the runtime handles sending different payload sizes. +func BenchmarkNginxDocSize(b *testing.B) { + benchmarkHttpdDocSize(b, false /* reverse */) +} - port := 80 - // Start the server. - if err := server.Spawn(ctx, - dockerutil.RunOpts{ - Image: "benchmarks/nginx", - Ports: []int{port}, - }); err != nil { - b.Fatalf("server failed to start: %v", err) - } +// BenchmarkReverseNginxDocSize iterates over different sized payloads, testing +// how well the runtime handles receiving different payload sizes. +func BenchmarkReverseNginxDocSize(b *testing.B) { + benchmarkHttpdDocSize(b, true /* reverse */) +} - ip, err := serverMachine.IPAddress() - if err != nil { - b.Fatalf("failed to find server ip: %v", err) +// benchmarkNginxDocSize iterates through all doc sizes, running subbenchmarks +// for each size. +func benchmarkNginxDocSize(b *testing.B, reverse bool) { + b.Helper() + for name, filename := range nginxDocs { + concurrency := []int{1, 25, 50, 100, 1000} + for _, c := range concurrency { + b.Run(fmt.Sprintf("%s_%d", name, c), func(b *testing.B) { + hey := &tools.Hey{ + Requests: c * b.N, + Concurrency: c, + Doc: filename, + } + runNginx(b, hey, reverse) + }) + } } +} - servingPort, err := server.FindPort(ctx, port) - if err != nil { - b.Fatalf("failed to find server port %d: %v", port, err) +// runNginx configures the static serving methods to run httpd. +func runNginx(b *testing.B, hey *tools.Hey, reverse bool) { + // nginx runs on port 80. + port := 80 + nginxRunOpts := dockerutil.RunOpts{ + Image: "benchmarks/nginx", + Ports: []int{port}, } - // Check the server is serving. - harness.WaitUntilServing(ctx, clientMachine, ip, servingPort) - - // Grab a client. - client := clientMachine.GetNativeContainer(ctx, b) - defer client.CleanUp(ctx) - - b.ResetTimer() - server.RestartProfiles() - for i := 0; i < b.N; i++ { - out, err := client.Run(ctx, dockerutil.RunOpts{ - Image: "benchmarks/hey", - }, hey.MakeCmd(ip, servingPort)...) - if err != nil { - b.Fatalf("run failed with: %v", err) - } - b.StopTimer() - hey.Report(b, out) - b.StartTimer() - } + // Command copies nginxDocs to tmpfs serving directory and runs nginx. + nginxCmd := []string{"sh", "-c", "mkdir -p /tmp/html && cp -a /local/* /tmp/html && nginx"} + runStaticServer(b, nginxRunOpts, nginxCmd, port, hey, reverse) } diff --git a/test/benchmarks/network/static_server.go b/test/benchmarks/network/static_server.go new file mode 100644 index 000000000..3ef62a71f --- /dev/null +++ b/test/benchmarks/network/static_server.go @@ -0,0 +1,88 @@ +// Copyright 2020 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package network + +import ( + "context" + "testing" + + "gvisor.dev/gvisor/pkg/test/dockerutil" + "gvisor.dev/gvisor/test/benchmarks/harness" + "gvisor.dev/gvisor/test/benchmarks/tools" +) + +// runStaticServer runs static serving workloads (httpd, nginx). +func runStaticServer(b *testing.B, serverOpts dockerutil.RunOpts, serverCmd []string, port int, hey *tools.Hey, reverse bool) { + b.Helper() + ctx := context.Background() + + // Get two machines: a client and server. + clientMachine, err := h.GetMachine() + if err != nil { + b.Fatalf("failed to get machine: %v", err) + } + defer clientMachine.CleanUp() + + serverMachine, err := h.GetMachine() + if err != nil { + b.Fatalf("failed to get machine: %v", err) + } + defer serverMachine.CleanUp() + + // Make the containers. 'reverse=true' specifies that the client should use the + // runtime under test. + var client, server *dockerutil.Container + if reverse { + client = clientMachine.GetContainer(ctx, b) + server = serverMachine.GetNativeContainer(ctx, b) + } else { + client = clientMachine.GetNativeContainer(ctx, b) + server = serverMachine.GetContainer(ctx, b) + } + defer client.CleanUp(ctx) + defer server.CleanUp(ctx) + + // Start the server. + if err := server.Spawn(ctx, serverOpts, serverCmd...); err != nil { + 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) + b.ResetTimer() + server.RestartProfiles() + out, err := client.Run(ctx, dockerutil.RunOpts{ + Image: "benchmarks/hey", + }, hey.MakeCmd(ip, servingPort)...) + if err != nil { + b.Fatalf("run failed with: %v", err) + } + + b.StopTimer() + hey.Report(b, out) + b.StartTimer() +} |