-
Notifications
You must be signed in to change notification settings - Fork 38.7k
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
Faster scheduler #77509
Merged
Merged
Faster scheduler #77509
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ type NodeTree struct { | |
tree map[string]*nodeArray // a map from zone (region-zone) to an array of nodes in the zone. | ||
zones []string // a list of all the zones in the tree (keys) | ||
zoneIndex int | ||
allNodes []string | ||
numNodes int | ||
mu sync.RWMutex | ||
} | ||
|
@@ -92,6 +93,7 @@ func (nt *NodeTree) addNode(n *v1.Node) { | |
} | ||
klog.V(5).Infof("Added node %v in group %v to NodeTree", n.Name, zone) | ||
nt.numNodes++ | ||
nt.recomputeAllNodes() | ||
} | ||
|
||
// RemoveNode removes a node from the NodeTree. | ||
|
@@ -112,6 +114,7 @@ func (nt *NodeTree) removeNode(n *v1.Node) error { | |
} | ||
klog.V(5).Infof("Removed node %v in group %v from NodeTree", n.Name, zone) | ||
nt.numNodes-- | ||
nt.recomputeAllNodes() | ||
return nil | ||
} | ||
} | ||
|
@@ -159,9 +162,7 @@ func (nt *NodeTree) resetExhausted() { | |
|
||
// Next returns the name of the next node. NodeTree iterates over zones and in each zone iterates | ||
// over nodes in a round robin fashion. | ||
func (nt *NodeTree) Next() string { | ||
nt.mu.Lock() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you confirm that the lock here should be deleted? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is actually the main goal of this PR, removing the contention here. |
||
defer nt.mu.Unlock() | ||
func (nt *NodeTree) next() string { | ||
if len(nt.zones) == 0 { | ||
return "" | ||
} | ||
|
@@ -186,6 +187,22 @@ func (nt *NodeTree) Next() string { | |
} | ||
} | ||
|
||
func (nt *NodeTree) recomputeAllNodes() { | ||
nt.allNodes = make([]string, 0, nt.numNodes) | ||
nt.resetExhausted() | ||
for i := 0; i < nt.numNodes; i++ { | ||
nt.allNodes = append(nt.allNodes, nt.next()) | ||
} | ||
} | ||
|
||
// AllNodes returns the list of nodes as they would be iterated by | ||
// Next() method. | ||
func (nt *NodeTree) AllNodes() []string { | ||
nt.mu.RLock() | ||
defer nt.mu.RUnlock() | ||
return nt.allNodes | ||
} | ||
|
||
// NumNodes returns the number of nodes. | ||
func (nt *NodeTree) NumNodes() int { | ||
nt.mu.RLock() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 have a question, how do we deal with the reduction in the number of Nodes using the index? Is it possible to change position(skipped a node) or index out of range?
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 modulo should handle this, it ensures that g.lastIndex is always between 0 and "number_of_nodes - 1". Please let me know if I didn't fully answer the question.
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.
Suppose the current number of nodes is 100, g. lastIndex is 90, but in the next scheduling loop, the number of nodes is reduced to 80, at this time g. lastIndex value does not exist.
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.
right, but we are taking the modulo: (90 + whatever) % 80 = a number between 0 and 79
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.
Ok, then will this break the fairness of each node being chosen? Because we can't guarantee which node nodes are deleted, we can't find the last time we left by indexing.
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.
Not really, this is pretty much the same semantics of the original code (if not better).
In the original code, we were relying on next to pick the node. nodeArray.next function resets to zero if the index was larger than the length of the node array, and so it has the exact same issue you are describing here: if the index was 90, and the next scheduling loop the number of nodes were reduced to 80, then the next node that will be picked up is always the one at index 0 irrespective of which nodes were removed.
The only difference with the new logic is that we don't reset to zero, we loop back, so in the example above, the next nodes will be picked starting from index 10. So in a way we improve fairness in that we don't always restart at the same place (zero).
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 is not necessarily better than the old code. In the old version of the code, fairness after adding/removing nodes was being kept by NodeTree. Now, the client of NodeTree preserves fairness. So, I think the final outcome is similar.