summaryrefslogtreecommitdiff
path: root/cmd/podman/shared/parallel.go
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-10-23 18:40:34 -0500
committerbaude <bbaude@redhat.com>2018-10-25 07:50:46 -0500
commit3e5a5c68da9884ddb46cb9e84435956996347a4b (patch)
treea4b169f923fc64b3fadab0bab8de711d677eb3c5 /cmd/podman/shared/parallel.go
parent57f778aed93efc0961b1335bcd07c3c82a11da0a (diff)
downloadpodman-3e5a5c68da9884ddb46cb9e84435956996347a4b.tar.gz
podman-3e5a5c68da9884ddb46cb9e84435956996347a4b.tar.bz2
podman-3e5a5c68da9884ddb46cb9e84435956996347a4b.zip
Add --max-workers and heuristics for parallel operations
add a global flag for --max-workers so users can limit the number of parallel operations for a given function. also, when not limited by max-workers, we implement a heuristic function that returns the number of preferred parallel workers based on the number of CPUs and the given operation. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'cmd/podman/shared/parallel.go')
-rw-r--r--cmd/podman/shared/parallel.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/cmd/podman/shared/parallel.go b/cmd/podman/shared/parallel.go
new file mode 100644
index 000000000..03eba2f0b
--- /dev/null
+++ b/cmd/podman/shared/parallel.go
@@ -0,0 +1,91 @@
+package shared
+
+import (
+ "runtime"
+ "sync"
+)
+
+type pFunc func() error
+
+// ParallelWorkerInput is a struct used to pass in a slice of parallel funcs to be
+// performed on a container ID
+type ParallelWorkerInput struct {
+ ContainerID string
+ ParallelFunc pFunc
+}
+
+type containerError struct {
+ ContainerID string
+ Err error
+}
+
+// ParallelWorker is a "threaded" worker that takes jobs from the channel "queue"
+func ParallelWorker(wg *sync.WaitGroup, jobs <-chan ParallelWorkerInput, results chan<- containerError) {
+ for j := range jobs {
+ err := j.ParallelFunc()
+ results <- containerError{ContainerID: j.ContainerID, Err: err}
+ wg.Done()
+ }
+}
+
+// ParallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker
+// int determines how many workers/threads should be premade.
+func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) map[string]error {
+ var (
+ wg sync.WaitGroup
+ )
+
+ resultChan := make(chan containerError, len(functions))
+ results := make(map[string]error)
+ paraJobs := make(chan ParallelWorkerInput, len(functions))
+
+ // If we have more workers than functions, match up the number of workers and functions
+ if workers > len(functions) {
+ workers = len(functions)
+ }
+
+ // Create the workers
+ for w := 1; w <= workers; w++ {
+ go ParallelWorker(&wg, paraJobs, resultChan)
+ }
+
+ // Add jobs to the workers
+ for _, j := range functions {
+ j := j
+ wg.Add(1)
+ paraJobs <- j
+ }
+
+ close(paraJobs)
+ wg.Wait()
+
+ close(resultChan)
+ for ctrError := range resultChan {
+ results[ctrError.ContainerID] = ctrError.Err
+ }
+
+ return results
+}
+
+// Parallelize provides the maximum number of parallel workers (int) as calculated by a basic
+// heuristic. This can be overriden by the --max-workers primary switch to podman.
+func Parallelize(job string) int {
+ numCpus := runtime.NumCPU()
+ switch job {
+ case "stop":
+ if numCpus <= 2 {
+ return 4
+ } else {
+ return numCpus * 3
+ }
+ case "rm":
+ if numCpus <= 3 {
+ return numCpus * 3
+ } else {
+ return numCpus * 4
+ }
+ case "ps":
+ return 8
+ }
+ return 3
+}