Repository: moby/moby
File: daemon/list.go (Go)

Code before:

	var (
		view       = daemon.containersReplica.Snapshot()
		containers = []*containertypes.Summary{}
	)

	filter, err := daemon.foldFilter(ctx, view, config)
	if err != nil {
		return nil, err
	}

	// shortcut to only look at a subset of containers if specific name
	// or ID matches were provided by the user--otherwise we potentially
	// end up querying many more containers than intended
	containerList, err := daemon.filterByNameIDMatches(view, filter)
	if err != nil {
		return nil, err
	}
	numContainers := len(containerList)
	results := make(chan *containertypes.Summary, numContainers)

	// Get the info for each container in the list; this can be slow so we
	// dispatch a set number of worker goroutines to do the jobs. We choose
	// log2(numContainers) workers to avoid creating too many goroutines
	// for large number of containers.
	numWorkers := log2(numContainers)
	if numWorkers < 1 {
		numWorkers = 1
	}
	workers := make(chan struct{}, numWorkers)

	var wg sync.WaitGroup
	for i := range containerList {
		currentContainer := &containerList[i]
		switch includeContainerInList(currentContainer, filter) {
		case excludeContainer:
			continue
		case stopIteration:
			break
		default:
			filter.idx++
			workers <- struct{}{} // acquire worker slot
			wg.Add(1)

			// worker function
			go func(c *container.Snapshot) {
				defer func() {
					wg.Done()
					<-workers // release worker slot
				}()


Review comment (suggestion):
Given that `log2` is literally a 1-line function and we describe here what we do, I think inlining it would make sense (keeping the implementation close to where it's used);

```suggestion
	numWorkers := int(math.Log2(float64(numContainers)))
```

Code after:
	}

	view := daemon.containersReplica.Snapshot()
	filter, err := daemon.foldFilter(ctx, view, config)
	if err != nil {
		return nil, err
	}

	// shortcut to only look at a subset of containers if specific name
	// or ID matches were provided by the user--otherwise we potentially
	// end up querying many more containers than intended
	//
	// TODO (thaJeztah): given containersReplica.Snapshot() provides a "consistent read-only view of the database" (which indicates "de-referenced copy", is there any reason we wouldn't use a []*container.Snapshot (pointer-slice)?.
	containerList, err := daemon.filterByNameIDMatches(view, filter)
	if err != nil {
		return nil, err
	}
	numContainers := len(containerList)

	// shortcut if there are no containers
	if numContainers == 0 {
		return []*containertypes.Summary{}, nil
	}

	// Get the info for each container in the list; this can be slow so we
	// dispatch a set number of worker goroutines to do the jobs. We choose
	// log2(numContainers) workers to avoid creating too many goroutines
	// for large number of containers.
	numWorkers := int(math.Log2(float64(numContainers)))
	if numWorkers < 1 {
		numWorkers = 1
	}

	resultsMut := sync.Mutex{}
	results := make([]*containertypes.Summary, numContainers)

	g, ctx := errgroup.WithContext(ctx)
	g.SetLimit(numWorkers)

	for i := range containerList {
		currentContainer := &containerList[i]
		stop := false
		switch includeContainerInList(currentContainer, filter) {
		case excludeContainer:
			continue
		case stopIteration:
			stop = true
		case includeContainer:
			idx := filter.idx
			filter.idx++