From 57d91179592eb43b6ab3706e6cc410af15dfb31c Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Mon, 24 Jun 2024 00:13:56 -0700 Subject: [PATCH] libct/int: add BenchmarkExecInBigEnv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here's what it shows on my laptop (with -count 10 -benchtime 10s, summarized by benchstat): name time/op ExecInBigEnv-20 61.7ms ± 4% Signed-off-by: Kir Kolyshkin --- libcontainer/integration/execin_test.go | 75 +++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/libcontainer/integration/execin_test.go b/libcontainer/integration/execin_test.go index b9683b76442..78e52a409ba 100644 --- a/libcontainer/integration/execin_test.go +++ b/libcontainer/integration/execin_test.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io" + "math/rand" "os" "strconv" "strings" @@ -377,6 +378,80 @@ func TestExecInEnvironment(t *testing.T) { } } +func genBigEnv(count int) []string { + randStr := func(length int) string { + const charset = "abcdefghijklmnopqrstuvwxyz0123456789_" + b := make([]byte, length) + for i := range b { + b[i] = charset[rand.Intn(len(charset))] + } + return string(b) + } + + envs := make([]string, count) + for i := 0; i < count; i++ { + key := strings.ToUpper(randStr(10)) + value := randStr(20) + envs[i] = key + "=" + value + } + + return envs +} + +func BenchmarkExecInBigEnv(b *testing.B) { + if testing.Short() { + return + } + 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 stdinW.Close() //nolint: errcheck + ok(b, err) + + const numEnv = 5000 + env := append(standardEnvironment, genBigEnv(numEnv)...) + // Construct the expected output. + var wantOut bytes.Buffer + for _, e := range env { + wantOut.WriteString(e + "\n") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + buffers := newStdBuffers() + process2 := &libcontainer.Process{ + Cwd: "/", + Args: []string{"env"}, + Env: env, + Stdin: buffers.Stdin, + Stdout: buffers.Stdout, + Stderr: buffers.Stderr, + } + err = container.Run(process2) + ok(b, err) + waitProcess(process2, b) + if !bytes.Equal(buffers.Stdout.Bytes(), wantOut.Bytes()) { + b.Fatalf("unexpected output: %s (stderr: %s)", buffers.Stdout, buffers.Stderr) + } + } + _ = stdinW.Close() + waitProcess(process, b) +} + func TestExecinPassExtraFiles(t *testing.T) { if testing.Short() { return