Integrate metricsviz library in gVisor benchmarks.

This is part of a series of changes to add metric charts in performance
benchmarks.

All benchmarks now auto-detect if profiling metrics are enabled in the test
runtime. If profiling metrics data is present, it will generate charts of
the data.

PiperOrigin-RevId: 633094699
This commit is contained in:
Etienne Perot
2024-05-12 22:49:38 -07:00
committed by gVisor bot
parent cf5c4c9cbf
commit cc665d1dcb
18 changed files with 98 additions and 28 deletions
+6
View File
@@ -26,6 +26,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/base",
"//test/benchmarks/harness",
"//test/metricsviz",
],
)
@@ -38,6 +39,7 @@ benchmark_test(
"//test/benchmarks/base",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -49,6 +51,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -60,6 +63,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -71,6 +75,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -82,6 +87,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
"@com_github_docker_docker//api/types:go_default_library",
],
)
+2
View File
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarHackbench runs hackbench on the runtime.
@@ -69,6 +70,7 @@ func BenchmarkHackbench(b *testing.B) {
); err != nil {
b.Fatalf("run failed with: %v", err)
}
defer metricsviz.FromContainerLogs(ctx, b, container)
cmd := tc.MakeCmd(b)
b.ResetTimer()
+10
View File
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/test/benchmarks/base"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkSizeEmpty creates N empty containers and reads memory usage from
@@ -58,6 +59,9 @@ func BenchmarkSizeEmpty(b *testing.B) {
base.CleanUpContainers(ctx, containers)
b.Fatalf("failed to run container: %v", err)
}
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, container)
}
if _, err := container.WaitForOutputSubmatch(ctx, "Hello", 5*time.Second); err != nil {
base.CleanUpContainers(ctx, containers)
b.Fatalf("failed to read container output: %v", err)
@@ -110,6 +114,9 @@ func BenchmarkSizeNginx(b *testing.B) {
Cmd: []string{"nginx", "-c", "/etc/nginx/nginx_gofer.conf"},
})
defer base.CleanUpContainers(ctx, servers)
if len(servers) > 0 {
defer metricsviz.FromContainerLogs(ctx, b, servers[0])
}
// DropCaches after servers are created.
harness.DropCaches(machine)
@@ -162,6 +169,9 @@ func BenchmarkSizeNode(b *testing.B) {
Cmd: nodeCmd,
})
defer base.CleanUpContainers(ctx, servers)
if len(servers) > 0 {
defer metricsviz.FromContainerLogs(ctx, b, servers[0])
}
// DropCaches after servers are created.
harness.DropCaches(machine)
+5
View File
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/base"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkStartEmpty times startup time for an empty container.
@@ -46,6 +47,9 @@ func BenchmarkStartupEmpty(b *testing.B) {
b.Fatalf("failed to start container: %v", err)
}
b.StopTimer()
if i == 0 {
metricsviz.FromContainerLogs(ctx, b, container)
}
container.CleanUp(ctx)
harness.DebugLog(b, "Ran container: %d", i)
}
@@ -113,6 +117,7 @@ func runServerWorkload(ctx context.Context, b *testing.B, args base.ServerArgs)
server := args.Machine.GetContainer(ctx, b)
defer func() {
b.StopTimer()
metricsviz.FromContainerLogs(ctx, b, server)
// Cleanup servers as we run so that we can go indefinitely.
server.CleanUp(ctx)
b.StartTimer()
+3 -1
View File
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
type testCase struct {
@@ -30,7 +31,7 @@ type testCase struct {
test tools.Sysbench
}
// BenchmarSysbench runs sysbench on the runtime.
// BenchmarkSysbench runs sysbench on the runtime.
func BenchmarkSysbench(b *testing.B) {
testCases := []testCase{
{
@@ -108,6 +109,7 @@ func BenchmarkSysbench(b *testing.B) {
ctx := context.Background()
sysbench := machine.GetContainer(ctx, b)
defer sysbench.CleanUp(ctx)
defer metricsviz.FromContainerLogs(ctx, b, sysbench)
cmd := tc.test.MakeCmd(b)
b.ResetTimer()
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarSyscallbench runs a syscall b.N times on the runtime.
@@ -67,6 +68,7 @@ func BenchmarkSyscallbench(b *testing.B) {
); err != nil {
b.Fatalf("run failed with: %v", err)
}
defer metricsviz.FromContainerLogs(ctx, b, container)
b.Run(name, func(b *testing.B) {
cmd := []string{"syscallbench", fmt.Sprintf("--loops=%d", b.N), fmt.Sprintf("--syscall=%d", tc.syscallArg)}
b.ResetTimer()
@@ -114,6 +116,7 @@ func BenchmarkSyscallUnderSeccomp(b *testing.B) {
); err != nil {
b.Fatalf("run failed with: %v", err)
}
defer metricsviz.FromContainerLogs(ctx, b, container)
b.Run(name, func(b *testing.B) {
cmd := []string{"syscallbench", "--syscall=1", fmt.Sprintf("--loops=%d", b.N)}
if tc.Value == "true" {
+10
View File
@@ -26,6 +26,7 @@ import (
"gvisor.dev/gvisor/test/benchmarks/base"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkSizeEmpty creates N alpine containers and reads memory usage using `docker stats`.
@@ -48,6 +49,9 @@ func BenchmarkSizeEmpty(b *testing.B) {
}, "sh", "-c", "echo Hello && sleep 1000"); err != nil {
b.Fatalf("failed to run container: %v", err)
}
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, container)
}
if _, err := container.WaitForOutputSubmatch(ctx, "Hello", 5*time.Second); err != nil {
b.Fatalf("failed to read container output: %v", err)
}
@@ -92,6 +96,9 @@ func BenchmarkSizeNginx(b *testing.B) {
b.Fatalf("failed to start server: %v", err)
}
defer server.CleanUp(ctx)
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, server)
}
stats, err := server.Stats(ctx)
if err != nil {
b.Fatalf("failed to get container stats: %v", err)
@@ -139,6 +146,9 @@ func BenchmarkSizeNode(b *testing.B) {
b.Fatalf("failed to start server: %v", err)
}
defer server.CleanUp(ctx)
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, server)
}
stats, err := server.Stats(ctx)
if err != nil {
b.Fatalf("failed to get container stats: %v", err)
+1
View File
@@ -29,6 +29,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
"@com_github_docker_docker//api/types/mount:go_default_library",
],
)
+2
View File
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// Fio benchmarks run fio on the runtime under test. There are 4 basic test
@@ -192,6 +193,7 @@ func doFioBenchmark(b *testing.B, testCases []tools.Fio) {
ctx := context.Background()
container := machine.GetContainer(ctx, b)
cu := cleanup.Make(func() {
metricsviz.FromContainerLogs(ctx, b, container)
container.CleanUp(ctx)
})
defer cu.Clean()
+1
View File
@@ -20,5 +20,6 @@ benchmark_test(
deps = [
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/metricsviz",
],
)
+18 -12
View File
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkFfmpeg runs ffmpeg in a container and records runtime.
@@ -39,19 +40,24 @@ func BenchmarkFfmpeg(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
container := machine.GetContainer(ctx, b)
defer container.CleanUp(ctx)
if err := harness.DropCaches(machine); err != nil {
b.Skipf("failed to drop caches: %v. You probably need root.", err)
}
func() {
container := machine.GetContainer(ctx, b)
defer container.CleanUp(ctx)
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, container)
}
if err := harness.DropCaches(machine); err != nil {
b.Skipf("failed to drop caches: %v. You probably need root.", err)
}
b.StartTimer()
if _, err := container.Run(ctx, dockerutil.RunOpts{
Image: "benchmarks/ffmpeg",
}, cmd...); err != nil {
b.Fatalf("failed to run container: %v", err)
}
b.StopTimer()
b.StartTimer()
if _, err := container.Run(ctx, dockerutil.RunOpts{
Image: "benchmarks/ffmpeg",
}, cmd...); err != nil {
b.Fatalf("failed to run container: %v", err)
}
b.StopTimer()
}()
}
}
+1
View File
@@ -21,5 +21,6 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
+21 -15
View File
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
func BenchmarkTensorflowDashboard(b *testing.B) {
@@ -70,22 +71,27 @@ func doTensorflowTest(b *testing.B, workloads map[string]string) {
b.StopTimer()
for i := 0; i < b.N; i++ {
container := machine.GetContainer(ctx, b)
defer container.CleanUp(ctx)
if err := harness.DropCaches(machine); err != nil {
b.Skipf("failed to drop caches: %v. You probably need root.", err)
}
func() {
container := machine.GetContainer(ctx, b)
defer container.CleanUp(ctx)
if i == 0 {
defer metricsviz.FromContainerLogs(ctx, b, container)
}
if err := harness.DropCaches(machine); err != nil {
b.Skipf("failed to drop caches: %v. You probably need root.", err)
}
// Run tensorflow.
b.StartTimer()
if out, err := container.Run(ctx, dockerutil.RunOpts{
Image: "benchmarks/tensorflow",
Env: []string{"PYTHONPATH=$PYTHONPATH:/TensorFlow-Examples/examples"},
WorkDir: "/TensorFlow-Examples/examples",
}, "python", file); err != nil {
b.Errorf("failed to run container: %v logs: %s", err, out)
}
b.StopTimer()
// Run tensorflow.
b.StartTimer()
if out, err := container.Run(ctx, dockerutil.RunOpts{
Image: "benchmarks/tensorflow",
Env: []string{"PYTHONPATH=$PYTHONPATH:/TensorFlow-Examples/examples"},
WorkDir: "/TensorFlow-Examples/examples",
}, "python", file); err != nil {
b.Errorf("failed to run container: %v logs: %s", err, out)
}
b.StopTimer()
}()
}
})
}
+4
View File
@@ -16,6 +16,7 @@ go_library(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -31,6 +32,7 @@ benchmark_test(
"//pkg/test/testutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -45,6 +47,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
@@ -59,6 +62,7 @@ benchmark_test(
"//pkg/test/dockerutil",
"//test/benchmarks/harness",
"//test/benchmarks/tools",
"//test/metricsviz",
],
)
+5
View File
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/test/testutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
func BenchmarkIperfOneConnection(b *testing.B) {
@@ -69,8 +70,10 @@ func BenchmarkIperfOneConnection(b *testing.B) {
// Set up the containers.
server := bm.serverFunc(ctx, b)
defer server.CleanUp(ctx)
defer metricsviz.FromNamedContainerLogs(ctx, b, server, "server")
client := bm.clientFunc(ctx, b)
defer client.CleanUp(ctx)
defer metricsviz.FromNamedContainerLogs(ctx, b, server, "client")
// iperf server listens on port 5001 by default.
port := 5001
@@ -180,8 +183,10 @@ func BenchmarkIperfManyConnections(b *testing.B) {
// Set up the containers.
server := bm.serverFunc(ctx, b)
defer server.CleanUp(ctx)
defer metricsviz.FromNamedContainerLogs(ctx, b, server, "server")
client := bm.clientFunc(ctx, b)
defer client.CleanUp(ctx)
defer metricsviz.FromNamedContainerLogs(ctx, b, client, "client")
// iperf server listens on port 5001 by default.
port := 5001
+2
View File
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// runStaticServer runs static serving workloads (httpd, nginx).
@@ -46,6 +47,7 @@ func runStaticServer(b *testing.B, serverOpts dockerutil.RunOpts, serverCmd []st
defer client.CleanUp(ctx)
server := serverMachine.GetContainer(ctx, b)
defer server.CleanUp(ctx)
defer metricsviz.FromContainerLogs(ctx, b, server)
// Start the server.
if err := server.Spawn(ctx, serverOpts, serverCmd...); err != nil {
+2
View File
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkNode runs requests using 'hey' against a Node server run on
@@ -78,6 +79,7 @@ func runNode(b *testing.B, hey *tools.Hey) {
b.Fatalf("failed to spawn redis instance: %v", err)
}
defer redis.CleanUp(ctx)
defer metricsviz.FromContainerLogs(ctx, b, redis)
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)
+2
View File
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/test/benchmarks/harness"
"gvisor.dev/gvisor/test/benchmarks/tools"
"gvisor.dev/gvisor/test/metricsviz"
)
// BenchmarkRuby runs requests using 'hey' against a ruby application server.
@@ -76,6 +77,7 @@ func runRuby(b *testing.B, hey *tools.Hey) {
b.Fatalf("failed to spawn redis instance: %v", err)
}
defer redis.CleanUp(ctx)
defer metricsviz.FromContainerLogs(ctx, b, redis)
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)