Skip to content

Refactor ImageService.Images#42578

Closed
rvolosatovs wants to merge 3 commits intomoby:masterfrom
rvolosatovs:optimize_image_query
Closed

Refactor ImageService.Images#42578
rvolosatovs wants to merge 3 commits intomoby:masterfrom
rvolosatovs:optimize_image_query

Conversation

@rvolosatovs
Copy link
Contributor

@rvolosatovs rvolosatovs commented Jun 29, 2021

A few things extracted from #42550

- What I did

  • Exit early when danglingOnly is true and a tag is found
  • Lazily initialize repo tag and digest slices, similarly to how it's done in the rest of the function
  • Introduce rangeImageLayerChainIDs for greater clarity and reducing code duplication

- How to verify it
Run docker images and docker system df

@rvolosatovs
Copy link
Contributor Author

rvolosatovs commented Jun 29, 2021

Blocked by #42550

@rvolosatovs
Copy link
Contributor Author

rvolosatovs commented Jun 29, 2021

@thaJeztah thaJeztah added kind/refactor PR's that refactor, or clean-up code status/2-code-review labels Jun 30, 2021
@rvolosatovs rvolosatovs force-pushed the optimize_image_query branch 2 times, most recently from 28a5773 to 927f1f0 Compare July 5, 2021 11:22
@rvolosatovs rvolosatovs force-pushed the optimize_image_query branch from 927f1f0 to 4c81533 Compare July 7, 2021 20:06
@rvolosatovs rvolosatovs force-pushed the optimize_image_query branch from 4c81533 to e94fddb Compare July 19, 2021 20:00
@rvolosatovs rvolosatovs marked this pull request as ready for review July 19, 2021 20:11
@rvolosatovs rvolosatovs force-pushed the optimize_image_query branch from e94fddb to 57555b1 Compare August 2, 2021 20:03
@rvolosatovs rvolosatovs marked this pull request as draft August 2, 2021 20:10
Roman Volosatovs added 3 commits August 5, 2021 16:25
- Lazily allocate the slices with capacity optimized for worst case
- Refactor the chain of if statements into a switch
- Support `repoDigests` and `repoTags` in image summary constructor

Signed-off-by: Roman Volosatovs <[email protected]>
- Refactor shared size computation:
    - Reduce nesting
    - Only mutate image summary struct once, on success

Signed-off-by: Roman Volosatovs <[email protected]>
@rvolosatovs rvolosatovs force-pushed the optimize_image_query branch from 57555b1 to d7cda41 Compare August 5, 2021 14:25
@rvolosatovs rvolosatovs changed the title Refactor and optimize ImageService.Images Refactor ImageService.Images Aug 5, 2021
@rvolosatovs rvolosatovs marked this pull request as ready for review August 5, 2021 14:28

// rangeImageLayerChainIDs calls f sequentially for chain ID of each layer image consists of.
// If f returns false, range stops the iteration.
func rangeImageLayerChainIDs(img *image.Image, f func(layer.ChainID) bool) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you just simply return an error in callback? (f func(layer.ChainID) error)
From what I see in the code below we return false if there is an error and true if not, no?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func rangeImageLayerChainIDs(img *image.Image, f func(layer.ChainID) error) error you can bubble up the error to be more precise

Copy link
Contributor Author

@rvolosatovs rvolosatovs Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason is really the consistency with https://pkg.go.dev/sync#Map.Range

But this is definitely an option and probably makes more sense in this case

Maybe naming it forEachImageLayerChainID is better then

Copy link
Contributor Author

@rvolosatovs rvolosatovs Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, after taking a closer look at this, I am not sure if returning an error in the callback is a cleaner solution here.

We have 2 usages here:

  1. https://github.com/moby/moby/pull/42578/files?w=1#diff-b62ea5c3b3e9f7f294e285690608fbd87d02686b780e1356f4c31652a9542fe7R246-R248 which iterates over all chain IDs always
  2. https://github.com/moby/moby/pull/42578/files?w=1#diff-b62ea5c3b3e9f7f294e285690608fbd87d02686b780e1356f4c31652a9542fe7R258-R274, which iterates over all chain IDs unless an error is encountered in one of the iterations

If we want to return an error in the callback, then discarding it seems wrong - at least that would not be "idiomatic", so if we want to return an error, I think we would need to propagate it up to the caller.

Now if we refactor it in this way, we get a marginal improvement in usage 2., since now we could wrap the function call into a shortened if as in if err := range...; err != nil and avoid one assignment to err from within the callback. For the usage 1. that would make it more confusing though, in my opinion: the iteration never errors, but now we'd need to either discard the error value returned by the function or check for != nil, which we know would never happen, which is IMO worse than a single assignment to err from within the callback in usage 2.

I.e. I don't think this is worth it:

			_ = rangeImageLayerChainIDs(img, func(chid layer.ChainID) error {
				layerRefs[chid]++
				return nil
			})

or

			if err := rangeImageLayerChainIDs(img, func(chid layer.ChainID) error {
				layerRefs[chid]++
				return nil
			}); err != nil {
				return err // or even panic, since this should never happen?
			}
			rangeImageLayerChainIDs(img, func(chid layer.ChainID) error {
				layerRefs[chid]++
				return nil
			})

is of course also possible, but that would be confusing, since right below we check for error and here we don't

Do you agree?

@rvolosatovs
Copy link
Contributor Author

Doesn't look like there's much need for this, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/refactor PR's that refactor, or clean-up code status/2-code-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants