-
Notifications
You must be signed in to change notification settings - Fork 388
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
[MRG] add "sticky builds" functionality #949
Conversation
The ranking is computed using the Rendez-vous hashing algorithm.
I'm happy to do this in small PRs if that feels right. It does make more reviewable bite-size chunks, but at the same time it makes it harder to figure out "why is it like this?" when the answer is in an as-yet unwritten PR. So my rough idea for breaking into smaller PRs:
So if I were breaking this into bits, I would probably do it the other way around - start with the PR where we add the ability to pick a node, with a no-op implementation to start, then the PR implementing a strategy using rendezvous hashing, etc. |
That makes sense. I'll try again with a second PR from the other end. |
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.
This PR ended up really fun to review, I ended up thinking a lot about many things and learning more about BinderHub. I found some ideas on improvements I hope you find concrete enough to apply if you agree they make sense!
Notes
|
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.
About the algorithm tests
Currently we have two tests. I think it is fine to have multiple tests and make them harder in descending sequence so we can fail on simple to understand test cases initially but also ensure statistically that we have a robust algorithm by making a strong test in the end.
|
||
def test_rendezvous_redistribution(): | ||
# check that approximately a third of keys move to the new bucket | ||
# when one is added |
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.
An idea for how to test that keys move when a new bucket becomes available and that the pattern of movement is right. I think this is how it should be but not sure. WDYT?
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.
Excellent!
Since we actually hash "nodes-key", this test doesn't need to be run multiple times, but if we would hash node separately from key and as consistent hashing was described to do as compared to our rendezvous hashing, then we could by fluke have two node hashes that are spaced luckily allow for the new node to to catch 1/3 of the stuff.
But hmmm, could you position nodes like pointers on a clock to initially have a fair share and then also after have a fair share?
Thats a clean test as well to have I think, to check that we have a 1/2 distribution initially and then get a 1/3 distribution after, combined with the previous test about perfectly stable we capture all kinds of logic. You are already doing this to some degree but it is captures mostly by the abs(from_b1 - from_b2) < 10
statement.
binderhub/tests/test_utils.py
Outdated
assert 0.31 < n_moved / n_keys < 0.35 | ||
# keys should move from the two original buckets with approximately | ||
# equal probability | ||
assert abs(from_b1 - from_b2) < 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.
Nice that you add a redistribution test, it makes me happy to grasp that this really works as we expect!
Assuming 1000 keys moved from either b1 or b2 and this is considered a coin flip, then the average difference will be sqrt(1000) which is about 31.6.
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 rounded it to 30. My feeling is that we just need to get the right order of magnitude here that fails the test when something really weird is happening and minimises false alarms.
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.
This currently LGTM!! Awesome work on this Tim!
I left some notes on the redistribution test but as they passed the narrow range by luck we can stick with it if you want!
assert abs(from_bucket["b1"] - from_bucket["b2"]) < 30 | ||
# the initial distribution of keys should be roughly the same | ||
# We pick 30 because it is "about right" | ||
assert abs(start_in["b1"] - start_in["b2"]) < 30 |
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.
The scale of the about right is different between the from_bucket and start_in difference, on average, the random walk distance if you flip a +1 or -1 over and over, is sqrt(N)
.
For the from_bucket case it is sqrt(~1000) == ~32
and for the start_in case it is sqrt(3000) == ~55
.
Keeps LGTM if you want to self-merge, I don't want to do it as you may want to finish up some detail though. |
Thanks for the ideas and patience!! I will try to find time today to deploy this on staging and watch what happens. |
The ranking is computed using the Rendez-vous hashing algorithm.
In the abstract this can be used for all sorts of stateless ranking, however this PR is part of #946 (comment) and provides a method for ranking possible nodes to schedule build pods on.
The goal is to eventually have a setup where
rendezvous_rank()
is called just before submitting the build pod spec to compute a preferred node for the pod:Let me know what you think of building this in small PRs. I'd propose to review and merge this without having to build out the rest.