-
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
scheduler: always edge merge in one direction #4559
Conversation
41fd3e9
to
9290b84
Compare
Woops, initial pass wasn't right - this was still vulnerable to deadlocks if:
The correct answer is to track every owner we merged into. |
Some stupid questions: Are these edges for different indexes? Then why would it matter that |
Yeah sorry 😁 The edges are unique, so are for different indexes. The vertices aren't merged, true - they're still entirely separate. The issue is that:
|
solver/jobs.go
Outdated
@@ -178,6 +180,7 @@ func (s *state) setEdge(index Index, targetEdge *edge, targetState *state) { | |||
targetState.mpw.Add(s.mpw) | |||
targetState.allPw[s.mpw] = struct{}{} | |||
} | |||
targetState.owners = append(targetState.owners, s.vtx) |
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.
Do we need this extra property? Can't we just cycle the .owner
chains of all sibling edges?
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.
Yup, looks like that works as well 🎉
solver/jobs.go
Outdated
@@ -280,6 +283,39 @@ func NewSolver(opts SolverOpt) *Solver { | |||
return jl | |||
} | |||
|
|||
func (jl *Solver) findMergeDirection(dest *edge, src *edge) (*edge, *edge) { |
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.
Would it be clearer if instead we used langauge "find if any sibling edge has already owned by the vertex of the targetedge"
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.
Have refactored this into a hasOwner
helper, then the caller determines whether to switch.
solver/scheduler.go
Outdated
@@ -351,6 +352,7 @@ func (s *scheduler) mergeTo(target, src *edge) bool { | |||
type edgeFactory interface { | |||
getEdge(Edge) *edge | |||
setEdge(Edge, *edge) | |||
findMergeDirection(*edge, *edge) (*edge, *edge) |
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't this logic be inside the setEdge
instead of exposed in this interface.
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.
Sadly not (this would be nice though).
We need to make sure we call s.ef.setEdge
in the right direction, but we also need to make sure we call s.mergeTo
in the right direction as well.
Signed-off-by: Justin Chadwell <[email protected]>
Signed-off-by: Justin Chadwell <[email protected]>
Previously, if this case occured, we would deadlock, so as to make this case more easily identifiable and debuggable, we should panic instead. Potentially, we could also just *skip* this case, but given that this is an internal logical error that should not occur, it would be better to identify this. Signed-off-by: Justin Chadwell <[email protected]>
When we perform a vertex merge, we should explicitly track the vertex that it was merged into. This way, we can avoid the case where we merge an index 0 edge from A->B and, later an index 1 edge from B->A. With this patch, this scenario instead flips the direction of the merge to merge from A->B for index 1. Signed-off-by: Justin Chadwell <[email protected]>
Signed-off-by: Justin Chadwell <[email protected]>
9290b84
to
b7a0282
Compare
Resolves #4347 (comment).
Previously, the scheduler could create cycles in the edges it merged:
Prior to #4347 this could (at worst) lead to a slight unnecessary inefficiency, where we would execute both A and B (even though both of their edges be merged so we'd never need to perform both of them). However, after this PR, we can accidentally deadlock, due to attempting to nest progress writers.