github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/integration-cli/benchmark_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "runtime" 8 "strings" 9 "sync" 10 "testing" 11 "time" 12 13 "github.com/docker/docker/integration-cli/cli" 14 "gotest.tools/v3/assert" 15 ) 16 17 type DockerBenchmarkSuite struct { 18 ds *DockerSuite 19 } 20 21 func (s *DockerBenchmarkSuite) TearDownTest(ctx context.Context, c *testing.T) { 22 s.ds.TearDownTest(ctx, c) 23 } 24 25 func (s *DockerBenchmarkSuite) OnTimeout(c *testing.T) { 26 s.ds.OnTimeout(c) 27 } 28 29 func (s *DockerBenchmarkSuite) BenchmarkConcurrentContainerActions(c *testing.B) { 30 maxConcurrency := runtime.GOMAXPROCS(0) 31 numIterations := c.N 32 outerGroup := &sync.WaitGroup{} 33 outerGroup.Add(maxConcurrency) 34 chErr := make(chan error, numIterations*2*maxConcurrency) 35 36 for i := 0; i < maxConcurrency; i++ { 37 go func() { 38 defer outerGroup.Done() 39 innerGroup := &sync.WaitGroup{} 40 innerGroup.Add(2) 41 42 go func() { 43 defer innerGroup.Done() 44 for i := 0; i < numIterations; i++ { 45 args := []string{"run", "-d", "busybox"} 46 args = append(args, sleepCommandForDaemonPlatform()...) 47 out, _, err := dockerCmdWithError(args...) 48 if err != nil { 49 chErr <- fmt.Errorf(out) 50 return 51 } 52 53 id := strings.TrimSpace(out) 54 tmpDir, err := os.MkdirTemp("", "docker-concurrent-test-"+id) 55 if err != nil { 56 chErr <- err 57 return 58 } 59 defer os.RemoveAll(tmpDir) 60 out, _, err = dockerCmdWithError("cp", id+":/tmp", tmpDir) 61 if err != nil { 62 chErr <- fmt.Errorf(out) 63 return 64 } 65 66 out, _, err = dockerCmdWithError("kill", id) 67 if err != nil { 68 chErr <- fmt.Errorf(out) 69 } 70 71 out, _, err = dockerCmdWithError("start", id) 72 if err != nil { 73 chErr <- fmt.Errorf(out) 74 } 75 76 out, _, err = dockerCmdWithError("kill", id) 77 if err != nil { 78 chErr <- fmt.Errorf(out) 79 } 80 81 // don't do an rm -f here since it can potentially ignore errors from the graphdriver 82 out, _, err = dockerCmdWithError("rm", id) 83 if err != nil { 84 chErr <- fmt.Errorf(out) 85 } 86 } 87 }() 88 89 go func() { 90 defer innerGroup.Done() 91 for i := 0; i < numIterations; i++ { 92 out, _, err := dockerCmdWithError("ps") 93 if err != nil { 94 chErr <- fmt.Errorf(out) 95 } 96 } 97 }() 98 99 innerGroup.Wait() 100 }() 101 } 102 103 outerGroup.Wait() 104 close(chErr) 105 106 for err := range chErr { 107 assert.NilError(c, err) 108 } 109 } 110 111 func (s *DockerBenchmarkSuite) BenchmarkLogsCLIRotateFollow(c *testing.B) { 112 out := cli.DockerCmd(c, "run", "-d", "--log-opt", "max-size=1b", "--log-opt", "max-file=10", "busybox", "sh", "-c", "while true; do usleep 50000; echo hello; done").Combined() 113 id := strings.TrimSpace(out) 114 ch := make(chan error, 1) 115 go func() { 116 ch <- nil 117 out, _, _ := dockerCmdWithError("logs", "-f", id) 118 // if this returns at all, it's an error 119 ch <- fmt.Errorf(out) 120 }() 121 122 <-ch 123 select { 124 case <-time.After(30 * time.Second): 125 // ran for 30 seconds with no problem 126 return 127 case err := <-ch: 128 if err != nil { 129 c.Fatal(err) 130 } 131 } 132 }