-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add concurrency to tag Lookup #3589
Conversation
This was to address performance issues when deleting images in repos with a large number of tagstore distribution#3525 Signed-off-by: jack-baines <jack.baines@uk.ibm.com>
Codecov Report
@@ Coverage Diff @@
## main #3589 +/- ##
==========================================
+ Coverage 56.33% 56.56% +0.22%
==========================================
Files 101 101
Lines 7313 7354 +41
==========================================
+ Hits 4120 4160 +40
- Misses 2536 2537 +1
Partials 657 657
Continue to review full report at Codecov.
|
This PR fixes 1 of the 2 things described in the issue which is that we have to look up every tag in the repo to detect whether it matches the digest being deleted and needs to be untagged and previously this was done one tag at a time. The 2nd bit has much lower impact from manual testing and is that once we have identified which tags match the digest we untag them sequentially. My view was this second change can be done standalone at a later date. |
My testing on a a relatively small repo showed a 3x improvement so deleting an image in a repo with 500 tags took ~6s down from ~18s. |
Final thing to point out is that I have hardcoded the concurrency limit to 10 obviously may be some advantages to that being configurable but wasn't entirely sure on how that could be achieved, so if that is deemed required would appreciate a pointer of a similar code that gets config into something like the tag store. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks good. I have a few nits if you don't mind :)
go func() { | ||
wg.Wait() | ||
close(tagChan) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove this empty line?
read: | ||
for { | ||
select { | ||
case err, workRemaining := <-errChan: | ||
if !workRemaining { | ||
break read | ||
} | ||
cancel() | ||
return nil, err | ||
case tag, workRemaining := <-tagChan: | ||
if !workRemaining { | ||
close(errChan) | ||
break read | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we move this code into a goroutine
(maybe allocate a chan and wait for it to finish?); it would be great to get rid of the break label 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for use gorountine,
done := make(chan bool, 1)
go func() {
defer func() {
done <- true
}()
for {
select {
case err, workRemaining := <-errChan:
if !workRemaining {
break read
}
cancel()
return nil, err
case tag, workRemaining := <-tagChan:
if !workRemaining {
close(errChan)
break read
}
tags = append(tags, tag)
}
}
}
<-done
@@ -149,26 +150,82 @@ func (ts *tagStore) Lookup(ctx context.Context, desc distribution.Descriptor) ([ | |||
return nil, err | |||
} | |||
|
|||
limiter := make(chan struct{}, 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we make 10
a constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and why chooses 10 or make it configurable just by env is enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'm all for making this configurable, but we could also have a fallthrough default value which should be a constant
Just wondering since we are addressing these slow deletes...this code in S3 delete driver could use a bit of TLC, too. If the repo contains a lot of data, we end up growing |
name: ts.repository.Named().Name(), | ||
tag: tag, | ||
} | ||
limiter <- struct{}{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like we can have a struct to wrap chan to provide public methods, that could be easy to understand.
My suggestion:
func NewWorkerPool(size int32) *WorkerPool {
wp := &WorkerPool{}
wp.queue = make(chan struct{}, size)
return wp
}
type WorkerPool struct {
queue chan struct{}
}
func (w *WorkerPool) GetWorker() {
w.queue <- struct{}{}
}
func (w *WorkerPool) ReleaseWorker() {
<-w.queue
}
LGTM... 800TB files in ceph ,its' hard to delete. delete file with 3TB / min |
Is there any news on this? |
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
Ping @bainsy88 |
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
Friendly ping @bainsy88 |
There is also #3890 which is more comprehensive. We need to decide which one to keep focussing on. |
If #3890 is more comprehensive and more (recently) active then I’d say it’s safe to close this PR (also given that the author hasn’t responded to the reviews). As always, feel free to re-open this PR. |
Based on distribution#3589 Signed-off-by: Andrey Voronkov <andrey.voronkov@sbermarket.ru>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <andrey.voronkov@sbermarket.ru>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <=>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
Based on distribution#3589 Signed-off-by: Andrey Voronkov <voronkovaa@gmail.com>
This was to address performance issues when deleting images in repos with a large number of tagstore
#3525
Signed-off-by: jack-baines jack.baines@uk.ibm.com