From 01657980c67d39533255dd4c0dc5d7d039c07f85 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 8 Oct 2024 17:20:14 -0700 Subject: [PATCH] libct/int: add exec benchmark This is a benchmark which checks how fast we can execute /bin/true inside a container. Results from my machine are below. As you can see, in default setup about 70% of exec time is spent for CVE-2019-5736 (copying runc binary), and using either RUNC_DMZ=true or memfd-bind helps a lot. This can also be used for profiling (using -test.cpuprofile option). === Default setup === [kir@kir-tp1 integration]$ sudo ./integration.test -test.run xxx -test.v -test.benchtime 5s -test.count 5 -test.bench . . goos: linux goarch: amd64 pkg: github.com/opencontainers/runc/libcontainer/integration cpu: 12th Gen Intel(R) Core(TM) i7-12800H BenchmarkExecTrue BenchmarkExecTrue-20 327 24475677 ns/op BenchmarkExecTrue-20 244 25242718 ns/op BenchmarkExecTrue-20 232 26187174 ns/op BenchmarkExecTrue-20 237 26780030 ns/op BenchmarkExecTrue-20 318 18487219 ns/op PASS === With DMZ enabled === [kir@kir-tp1 integration]$ sudo -E RUNC_DMZ=true ./integration.test -test.run xxx -test.v -test.benchtime 5s -test.count 5 -test.bench . . goos: linux goarch: amd64 pkg: github.com/opencontainers/runc/libcontainer/integration cpu: 12th Gen Intel(R) Core(TM) i7-12800H BenchmarkExecTrue BenchmarkExecTrue-20 694 8263744 ns/op BenchmarkExecTrue-20 778 8483228 ns/op BenchmarkExecTrue-20 784 8456018 ns/op BenchmarkExecTrue-20 732 8160239 ns/op BenchmarkExecTrue-20 769 8236972 ns/op PASS === With memfd-bind === [kir@kir-tp1 integration]$ sudo systemctl start memfd-bind@$(systemd-escape -p $PWD/integration.test) [kir@kir-tp1 integration]$ sudo ./integration.test -test.run xxx -test.v -test.benchtime 5s -test.count 5 -test.bench . . goos: linux goarch: amd64 pkg: github.com/opencontainers/runc/libcontainer/integration cpu: 12th Gen Intel(R) Core(TM) i7-12800H BenchmarkExecTrue BenchmarkExecTrue-20 800 7538839 ns/op BenchmarkExecTrue-20 717 7424755 ns/op BenchmarkExecTrue-20 848 7747787 ns/op BenchmarkExecTrue-20 800 7668740 ns/op BenchmarkExecTrue-20 751 7304373 ns/op PASS Signed-off-by: Kir Kolyshkin --- libcontainer/integration/bench_test.go | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 libcontainer/integration/bench_test.go diff --git a/libcontainer/integration/bench_test.go b/libcontainer/integration/bench_test.go new file mode 100644 index 00000000000..da95b20b0b7 --- /dev/null +++ b/libcontainer/integration/bench_test.go @@ -0,0 +1,51 @@ +package integration + +import ( + "os" + "testing" + + "github.com/opencontainers/runc/libcontainer" +) + +func BenchmarkExecTrue(b *testing.B) { + config := newTemplateConfig(b, nil) + container, err := newContainer(b, config) + ok(b, err) + defer destroyContainer(container) + + // Execute a first process in the container + stdinR, stdinW, err := os.Pipe() + ok(b, err) + process := &libcontainer.Process{ + Cwd: "/", + Args: []string{"cat"}, + Env: standardEnvironment, + Stdin: stdinR, + Init: true, + } + err = container.Run(process) + _ = stdinR.Close() + defer func() { + _ = stdinW.Close() + if _, err := process.Wait(); err != nil { + b.Log(err) + } + }() + ok(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + exec := &libcontainer.Process{ + Cwd: "/", + Args: []string{"/bin/true"}, + Env: standardEnvironment, + LogLevel: "0", // Minimize forwardChildLogs involvement. + } + err := container.Run(exec) + if err != nil { + b.Fatal("exec failed:", err) + } + waitProcess(exec, b) + } + b.StopTimer() +}