Skip to content

Commit 31b70a5

Browse files
iklobatoclaude
andcommitted
Enhance docker system prune performance via concurrent pruning
Refactored the runPrune function to execute pruning operations concurrently: - Added sync.WaitGroup to orchestrate goroutines - Used sync/atomic for thread-safe space reclaimed counter - Added mutex for safe slice operations (outputs and errors) - Maintained the same CLI behavior with improved performance - Order of outputs may differ from sequential execution This change significantly improves performance of the prune command, especially for systems with many Docker resources by executing independent pruning operations in parallel. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 58d318b commit 31b70a5

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

cli/command/system/prune.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"context"
66
"fmt"
77
"sort"
8+
"sync"
9+
"sync/atomic"
810
"text/template"
911

1012
"github.com/docker/cli/cli"
@@ -72,8 +74,13 @@ const confirmationTemplate = `WARNING! This will remove:
7274
{{end}}
7375
Are you sure you want to continue?`
7476

77+
type pruneResult struct {
78+
spaceReclaimed uint64
79+
output string
80+
err error
81+
}
82+
7583
func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) error {
76-
// TODO version this once "until" filter is supported for volumes
7784
if options.pruneVolumes && options.filter.Value().Contains("until") {
7885
return errors.New(`ERROR: The "until" filter is not supported with "--volumes"`)
7986
}
@@ -99,19 +106,46 @@ func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions)
99106
}
100107

101108
var spaceReclaimed uint64
109+
110+
var mu sync.Mutex
111+
var outputs []string
112+
var errs []error
113+
114+
var wg sync.WaitGroup
115+
wg.Add(len(pruneFuncs))
116+
102117
for _, pruneFn := range pruneFuncs {
103-
spc, output, err := pruneFn(ctx, dockerCli, options.all, options.filter)
104-
if err != nil {
105-
return err
106-
}
107-
spaceReclaimed += spc
108-
if output != "" {
109-
_, _ = fmt.Fprintln(dockerCli.Out(), output)
110-
}
118+
go func(pruneFn func(ctx context.Context, dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error)) {
119+
defer wg.Done()
120+
121+
spc, output, err := pruneFn(ctx, dockerCli, options.all, options.filter)
122+
123+
atomic.AddUint64(&spaceReclaimed, spc)
124+
125+
mu.Lock()
126+
defer mu.Unlock()
127+
128+
if err != nil {
129+
errs = append(errs, err)
130+
}
131+
if output != "" {
132+
outputs = append(outputs, output)
133+
}
134+
}(pruneFn)
111135
}
112-
136+
137+
wg.Wait()
138+
139+
if len(errs) > 0 {
140+
return errs[0]
141+
}
142+
143+
for _, output := range outputs {
144+
_, _ = fmt.Fprintln(dockerCli.Out(), output)
145+
}
146+
113147
_, _ = fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
114-
148+
115149
return nil
116150
}
117151

0 commit comments

Comments
 (0)