-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
cache: convert prune loop from recursive invocation to iterative #5636
base: master
Are you sure you want to change the base?
Conversation
The prune logic would prune multiple times because one prune could cause more things to be capable of pruning and change the logic. This was done through a recursive invocation. Since go doesn't have support for function tail calls, this would result in a new stack entry for each loop. This unrolls the logic so the prune function is invoked iteratively rather than recursively. `prune` and `pruneOnce` have also had their names swapped. In general, `pruneOnce` implies that it runs a single prune while `prune` sounds like the top level function. The current code had this reversed and `pruneOnce` would call `prune` and `prune` would call itself recursively. I've also updated a section in the controller that invoked prune on each worker. In older versions of Go, the current version was correct because those versions of Go would reuse the location for each loop which would cause goroutines to all reference the same worker instead of different workers. Recent versions of Go have changed the behavior so this is no longer needed. Signed-off-by: Jonathan A. Sternberg <[email protected]>
return err | ||
} | ||
totalReleasedSize += releasedSize | ||
totalReleasedCount += releasedCount |
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.
Where are these used?
}) | ||
} | ||
for { | ||
releasedSize, releasedCount, err := cm.pruneOnce(ctx, ch, popt) |
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.
releasedCount
in here seems more like a bool indicating if anything was pruned (unless I'm missing some usage of totalReleasedCount
).
return nil | ||
}) | ||
}(w) | ||
eg.Go(func() error { |
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 guess this is go1.22+ only
The prune logic would prune multiple times because one prune could cause more things to be capable of pruning and change the logic. This was done through a recursive invocation.
Since go doesn't have support for function tail calls, this would result in a new stack entry for each loop. This unrolls the logic so the prune function is invoked iteratively rather than recursively.
prune
andpruneOnce
have also had their names swapped. In general,pruneOnce
implies that it runs a single prune whileprune
sounds like the top level function. The current code had this reversed andpruneOnce
would callprune
andprune
would call itself recursively.I've also updated a section in the controller that invoked prune on each worker. In older versions of Go, the current version was correct because those versions of Go would reuse the location for each loop which would cause goroutines to all reference the same worker instead of different workers.
Recent versions of Go have changed the behavior so this is no longer needed.