From f256d8ad2d1fbd9407d2b7a8eb69c96665c4015e Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Thu, 15 Oct 2015 13:09:30 -0700 Subject: [PATCH] Speedup container list Remove all unneeded disk operations (reload TagStore, umarshal image) for checking if image still points to same ID. Now slowest part is queries to sqlite which hopefuly will be removed soon. Signed-off-by: Alexander Morozov --- daemon/list.go | 30 ++++++++++++++++++++++-------- graph/tags.go | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/daemon/list.go b/daemon/list.go index c35245be32..054fea4a52 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -9,6 +9,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" derr "github.com/docker/docker/errors" + "github.com/docker/docker/graph" "github.com/docker/docker/image" "github.com/docker/docker/pkg/graphdb" "github.com/docker/docker/pkg/nat" @@ -285,6 +286,24 @@ func includeContainerInList(container *Container, ctx *listContext) iterationAct return includeContainer } +func getImage(s *graph.TagStore, img, imgID string) (string, error) { + // both Image and ImageID is actually ids, nothing to guess + if strings.HasPrefix(imgID, img) { + return img, nil + } + id, err := s.GetID(img) + if err != nil { + if err == graph.ErrNameIsNotExist { + return imgID, nil + } + return "", err + } + if id != imgID { + return imgID, nil + } + return img, nil +} + // transformContainer generates the container type expected by the docker ps command. func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) (*types.Container, error) { newC := &types.Container{ @@ -297,16 +316,11 @@ func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) newC.Names = []string{} } - img, err := daemon.repositories.LookupImage(container.Config.Image) + showImg, err := getImage(daemon.repositories, container.Config.Image, container.ImageID) if err != nil { - // If the image can no longer be found by its original reference, - // it makes sense to show the ID instead of a stale reference. - newC.Image = container.ImageID - } else if container.ImageID == img.ID { - newC.Image = container.Config.Image - } else { - newC.Image = container.ImageID + return nil, err } + newC.Image = showImg if len(container.Args) > 0 { args := []string{} diff --git a/graph/tags.go b/graph/tags.go index a0349e67b9..b212fd93ba 100644 --- a/graph/tags.go +++ b/graph/tags.go @@ -24,6 +24,9 @@ import ( "github.com/docker/libtrust" ) +// ErrNameIsNotExist returned when there is no image with requested name. +var ErrNameIsNotExist = errors.New("image with specified name does not exist") + // TagStore manages repositories. It encompasses the Graph used for versioned // storage, as well as various services involved in pushing and pulling // repositories. @@ -164,6 +167,26 @@ func (store *TagStore) LookupImage(name string) (*image.Image, error) { return img, nil } +// GetID returns ID for image name. +func (store *TagStore) GetID(name string) (string, error) { + repoName, ref := parsers.ParseRepositoryTag(name) + if ref == "" { + ref = tags.DefaultTag + } + store.Lock() + defer store.Unlock() + repoName = registry.NormalizeLocalName(repoName) + repo, ok := store.Repositories[repoName] + if !ok { + return "", ErrNameIsNotExist + } + id, ok := repo[ref] + if !ok { + return "", ErrNameIsNotExist + } + return id, nil +} + // ByID returns a reverse-lookup table of all the names which refer to each // image - e.g. {"43b5f19b10584": {"base:latest", "base:v1"}} func (store *TagStore) ByID() map[string][]string {