Files
runc/libcontainer/integration/bench_test.go
Kir Kolyshkin 9a54594752 libct/int: add BenchmarkExecInBigEnv
Here's what it shows on my laptop (with -count 10 -benchtime 10s,
summarized by benchstat):

	                │   sec/op    │
	ExecTrue-20       8.477m ± 2%
	ExecInBigEnv-20   61.53m ± 1%

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-01-09 18:22:53 +08:00

124 lines
2.6 KiB
Go

package integration
import (
"bytes"
"math/rand"
"os"
"strings"
"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()
waitProcess(process, b)
}()
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)
ok(b, err)
waitProcess(exec, b)
}
b.StopTimer()
}
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) {
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()
waitProcess(process, b)
}()
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()
exec := &libcontainer.Process{
Cwd: "/",
Args: []string{"env"},
Env: env,
Stdin: buffers.Stdin,
Stdout: buffers.Stdout,
Stderr: buffers.Stderr,
}
err = container.Run(exec)
ok(b, err)
waitProcess(exec, b)
if !bytes.Equal(buffers.Stdout.Bytes(), wantOut.Bytes()) {
b.Fatalf("unexpected output: %s (stderr: %s)", buffers.Stdout, buffers.Stderr)
}
}
b.StopTimer()
}