feat(server): Order layers in image manifest based on merge rating

Image layers in manifests are now sorted in a stable (descending)
order based on their merge rating, meaning that layers more likely to
be shared between images come first.

The reason for this change is Docker's handling of image layers on
overlayfs2: Images are condensed into a single representation on disk
after downloading.

Due to this Docker will constantly redownload all layers that are
applied in a different order in different images (layer order matters
in imperatively created images), based on something it calls the
'ChainID'.

Sorting the layers this way raises the likelihood of a long chain of
matching layers at the beginning of an image.

This relates to #39.
This commit is contained in:
Vincent Ambo 2019-10-03 20:18:40 +01:00 committed by Vincent Ambo
parent 0d820423e9
commit 48a5ecda97
3 changed files with 20 additions and 4 deletions

View file

@ -141,7 +141,7 @@ type Popularity = map[string]int
// build for the container image.
type Layer struct {
Contents []string `json:"contents"`
mergeRating uint64
MergeRating uint64
}
// Hash the contents of a layer to create a deterministic identifier that can be
@ -153,7 +153,7 @@ func (l *Layer) Hash() string {
func (a Layer) merge(b Layer) Layer {
a.Contents = append(a.Contents, b.Contents...)
a.mergeRating += b.mergeRating
a.MergeRating += b.MergeRating
return a
}
@ -291,7 +291,7 @@ func groupLayer(dt *flow.DominatorTree, root *closure) Layer {
// both the size and the popularity when making merge
// decisions, but there might be a smarter way to do
// it than a plain multiplication.
mergeRating: uint64(root.Popularity) * size,
MergeRating: uint64(root.Popularity) * size,
}
}
@ -309,7 +309,7 @@ func dominate(budget int, graph *simple.DirectedGraph) []Layer {
}
sort.Slice(layers, func(i, j int) bool {
return layers[i].mergeRating < layers[j].mergeRating
return layers[i].MergeRating < layers[j].MergeRating
})
if len(layers) > budget {