Skip to content

Commit

Permalink
Image list optimization
Browse files Browse the repository at this point in the history
Signed-off-by: apostasie <spam_blackhole@farcloser.world>
  • Loading branch information
apostasie committed May 22, 2024
1 parent 88cb67b commit 8f89ec2
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 140 deletions.
38 changes: 3 additions & 35 deletions pkg/cmd/container/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/containerd/nerdctl/v2/pkg/containerinspector"
"github.com/containerd/nerdctl/v2/pkg/formatter"
"github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker"
"github.com/containerd/nerdctl/v2/pkg/imgutil"
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
)

Expand All @@ -36,7 +37,7 @@ func Inspect(ctx context.Context, client *containerd.Client, containers []string
f := &containerInspector{
mode: options.Mode,
size: options.Size,
snapshotter: client.SnapshotService(options.GOptions.Snapshotter),
snapshotter: imgutil.SnapshotServiceWithCache(client.SnapshotService(options.GOptions.Snapshotter)),
}

walker := &containerwalker.ContainerWalker{
Expand All @@ -61,39 +62,6 @@ type containerInspector struct {
entries []interface{}
}

// resourceTotal will return:
// - the Usage value of the resource referenced by ID
// - the cumulative Usage value of the resource, and all parents, recursively
// Typically, for a running container, this will equal the size of the read-write layer, plus the sum of the size of all layers in the base image
func resourceTotal(ctx context.Context, snapshotter snapshots.Snapshotter, resourceID string) (snapshots.Usage, snapshots.Usage, error) {
var first snapshots.Usage
var total snapshots.Usage
var info snapshots.Info

for next := resourceID; next != ""; next = info.Parent {
// Get the resource usage info
usage, err := snapshotter.Usage(ctx, next)
if err != nil {
return first, total, err
}
// In case that's the first one, store that
if next == resourceID {
first = usage
}
// And increment totals
total.Size += usage.Size
total.Inodes += usage.Inodes

// Now, get the parent, if any and iterate
info, err = snapshotter.Stat(ctx, next)
if err != nil {
return first, total, err
}
}

return first, total, nil
}

func (x *containerInspector) Handler(ctx context.Context, found containerwalker.Found) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
Expand All @@ -111,7 +79,7 @@ func (x *containerInspector) Handler(ctx context.Context, found containerwalker.
return err
}
if x.size {
resourceUsage, allResourceUsage, err := resourceTotal(ctx, x.snapshotter, d.ID)
resourceUsage, allResourceUsage, err := imgutil.ResourceUsage(ctx, x.snapshotter, d.ID)
if err == nil {
d.SizeRw = &resourceUsage.Size
d.SizeRootFs = &allResourceUsage.Size
Expand Down
32 changes: 13 additions & 19 deletions pkg/cmd/container/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import (
"time"

"github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/progress"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/log"
"github.com/containerd/nerdctl/v2/pkg/api/types"
"github.com/containerd/nerdctl/v2/pkg/formatter"
Expand Down Expand Up @@ -107,6 +107,7 @@ func (x *ListItem) Label(s string) string {

func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) {
listItems := make([]ListItem, len(containers))
snapshottersCache := map[string]snapshots.Snapshotter{}
for i, c := range containers {
info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata)
if err != nil {
Expand Down Expand Up @@ -141,7 +142,12 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container
Labels: info.Labels,
}
if options.Size {
containerSize, err := getContainerSize(ctx, client, c, info)
snapshotter, ok := snapshottersCache[info.Snapshotter]
if !ok {
snapshottersCache[info.Snapshotter] = imgutil.SnapshotServiceWithCache(client.SnapshotService(info.Snapshotter))
snapshotter = snapshottersCache[info.Snapshotter]
}
containerSize, err := getContainerSize(ctx, snapshotter, info.SnapshotKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -180,30 +186,18 @@ func getContainerNetworks(containerLables map[string]string) []string {
return networks
}

func getContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) {
func getContainerSize(ctx context.Context, snapshotter snapshots.Snapshotter, snapshotKey string) (string, error) {
// get container snapshot size
snapshotKey := info.SnapshotKey
var containerSize int64
var imageSize int64

if snapshotKey != "" {
usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey)
rw, all, err := imgutil.ResourceUsage(ctx, snapshotter, snapshotKey)
if err != nil {
return "", err
}
containerSize = usage.Size
}

// get the image interface
image, err := c.Image(ctx)
if err != nil {
return "", err
}

sn := client.SnapshotService(info.Snapshotter)

imageSize, err := imgutil.UnpackedImageSize(ctx, sn, image)
if err != nil {
return "", err
containerSize = rw.Size
imageSize = all.Size
}

return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil
Expand Down
4 changes: 3 additions & 1 deletion pkg/cmd/image/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/containerd/nerdctl/v2/pkg/formatter"
"github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker"
"github.com/containerd/nerdctl/v2/pkg/imageinspector"
"github.com/containerd/nerdctl/v2/pkg/imgutil"
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
)

Expand All @@ -35,13 +36,14 @@ func Inspect(ctx context.Context, client *containerd.Client, images []string, op
f := &imageInspector{
mode: options.Mode,
}
snapshotter := imgutil.SnapshotServiceWithCache(client.SnapshotService(options.GOptions.Snapshotter))
walker := &imagewalker.ImageWalker{
Client: client,
OnFound: func(ctx context.Context, found imagewalker.Found) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()

n, err := imageinspector.Inspect(ctx, client, found.Image, options.GOptions.Snapshotter)
n, err := imageinspector.Inspect(ctx, client, found.Image, snapshotter)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 8f89ec2

Please sign in to comment.