@@ -3,8 +3,10 @@ package containerd
33import (
44 "context"
55 "encoding/json"
6+ "runtime"
67 "sort"
78 "strings"
9+ "sync"
810 "time"
911
1012 "github.com/containerd/containerd/content"
@@ -27,6 +29,7 @@ import (
2729 "github.com/opencontainers/image-spec/identity"
2830 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
2931 "github.com/pkg/errors"
32+ "golang.org/x/sync/errgroup"
3033)
3134
3235// Subset of ocispec.Image that only contains Labels
@@ -91,16 +94,6 @@ func (i *ImageService) Images(ctx context.Context, opts imagetypes.ListOptions)
9194 return usage .Size , nil
9295 }
9396
94- var (
95- summaries = make ([]* imagetypes.Summary , 0 , len (imgs ))
96- root []* []digest.Digest
97- layers map [digest.Digest ]int
98- )
99- if opts .SharedSize {
100- root = make ([]* []digest.Digest , 0 , len (imgs ))
101- layers = make (map [digest.Digest ]int )
102- }
103-
10497 uniqueImages := map [digest.Digest ]images.Image {}
10598 tagsByDigest := map [digest.Digest ][]string {}
10699 intermediateImages := map [digest.Digest ]struct {}{}
@@ -152,24 +145,48 @@ func (i *ImageService) Images(ctx context.Context, opts imagetypes.ListOptions)
152145 tagsByDigest [dgst ] = append (tagsByDigest [dgst ], reference .FamiliarString (ref ))
153146 }
154147
148+ resultsMut := sync.Mutex {}
149+ eg , egCtx := errgroup .WithContext (ctx )
150+ eg .SetLimit (runtime .NumCPU () * 2 )
151+
152+ var (
153+ summaries = make ([]* imagetypes.Summary , 0 , len (imgs ))
154+ root []* []digest.Digest
155+ layers map [digest.Digest ]int
156+ )
157+ if opts .SharedSize {
158+ root = make ([]* []digest.Digest , 0 , len (imgs ))
159+ layers = make (map [digest.Digest ]int )
160+ }
161+
155162 for _ , img := range uniqueImages {
156- image , allChainsIDs , err := i .imageSummary (ctx , img , platformMatcher , opts , tagsByDigest )
157- if err != nil {
158- return nil , err
159- }
160- // No error, but image should be skipped.
161- if image == nil {
162- continue
163- }
163+ img := img
164+ eg .Go (func () error {
165+ image , allChainsIDs , err := i .imageSummary (egCtx , img , platformMatcher , opts , tagsByDigest )
166+ if err != nil {
167+ return err
168+ }
169+ // No error, but image should be skipped.
170+ if image == nil {
171+ return nil
172+ }
164173
165- summaries = append (summaries , image )
174+ resultsMut .Lock ()
175+ summaries = append (summaries , image )
166176
167- if opts .SharedSize {
168- root = append (root , & allChainsIDs )
169- for _ , id := range allChainsIDs {
170- layers [id ] = layers [id ] + 1
177+ if opts .SharedSize {
178+ root = append (root , & allChainsIDs )
179+ for _ , id := range allChainsIDs {
180+ layers [id ] = layers [id ] + 1
181+ }
171182 }
172- }
183+ resultsMut .Unlock ()
184+ return nil
185+ })
186+ }
187+
188+ if err := eg .Wait (); err != nil {
189+ return nil , err
173190 }
174191
175192 if opts .SharedSize {
0 commit comments