-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[red-knot] Optimise visibility constraints for *
-import definitions
#17317
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
Conversation
|
CodSpeed Performance ReportMerging #17317 will improve performances by 10.3%Comparing Summary
Benchmarks breakdown
|
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!
let constraint_id = self | ||
.current_use_def_map_mut() | ||
.record_star_import_visibility_constraint( | ||
star_import, | ||
symbol_id, | ||
); | ||
|
||
let post_definition = self.flow_snapshot(); | ||
self.flow_restore(pre_definition); | ||
|
||
self.current_use_def_map_mut() | ||
.negate_star_import_visibility_constraint( | ||
symbol_id, | ||
constraint_id, | ||
); | ||
|
||
self.flow_merge(post_definition); |
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 reclaims almost all the lost perf, so it seems fine to just go ahead with it as-is. But it still seems like we do more work here than necessary? In the newly-added case, we shouldn't have to do any snapshotting or flow-state merging at all. We can just add the star-import definition, apply the (positive) visibility constraint to it, and move on.
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.
As in, something like this (relative to my PR)? Quite a lot of tests start failing if I apply this diff...
diff --git a/crates/red_knot_python_semantic/src/semantic_index/builder.rs b/crates/red_knot_python_semantic/src/semantic_index/builder.rs
index 486482f7f..406014831 100644
--- a/crates/red_knot_python_semantic/src/semantic_index/builder.rs
+++ b/crates/red_knot_python_semantic/src/semantic_index/builder.rs
@@ -1219,23 +1219,12 @@ where
// we can apply the visibility constraint to *only* the added definition,
// rather than all definitions
if newly_added {
- let constraint_id = self
+ self
.current_use_def_map_mut()
.record_star_import_visibility_constraint(
star_import,
symbol_id,
);
-
- let post_definition = self.flow_snapshot();
- self.flow_restore(pre_definition);
-
- self.current_use_def_map_mut()
- .negate_star_import_visibility_constraint(
- symbol_id,
- constraint_id,
- );
-
- self.flow_merge(post_definition);
} else {
let constraint_id =
self.record_visibility_constraint(star_import.into());
diff --git a/crates/red_knot_python_semantic/src/semantic_index/use_def.rs b/crates/red_knot_python_semantic/src/semantic_index/use_def.rs
index edb27d26e..002faf319 100644
--- a/crates/red_knot_python_semantic/src/semantic_index/use_def.rs
+++ b/crates/red_knot_python_semantic/src/semantic_index/use_def.rs
@@ -713,19 +713,6 @@ impl<'db> UseDefMapBuilder<'db> {
visibility_id
}
- pub(super) fn negate_star_import_visibility_constraint(
- &mut self,
- symbol_id: ScopedSymbolId,
- constraint: ScopedVisibilityConstraintId,
- ) {
- let negated_constraint = self.visibility_constraints.add_not_constraint(constraint);
- self.symbol_states[symbol_id]
- .record_visibility_constraint(&mut self.visibility_constraints, negated_constraint);
- self.scope_start_visibility = self
- .visibility_constraints
- .add_and_constraint(self.scope_start_visibility, negated_constraint);
- }
-
/// This method resets the visibility constraints for all symbols to a previous state
/// *if* there have been no new declarations or bindings since then. Consider the
/// following example:
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'll go ahead and merge for now, but feel free to file a followup PR if you can see a way of optimising this further without breaking all my tests ;)
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 something I also didn't think about when writing that message on Discord, but I think you would also need to apply the negated visibility constraint to the implicit symbol = <unbound>
binding (it is stored as a None
entry at the beginning of the vector). I think that should allow you to get rid of snapshotting entirely for the "fast path".
We would basically still model
if <placeholder>:
from module import symbol
else:
symbol = <unbound>
but with the advantage that the constraint does not need to be applied to anything else.
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.
Ah yeah, that's because "unbound" is a binding also, and we do need to apply the negated visibility constraint to the "unbound" binding. (The "unbound" binding is visible only if the star import target symbol does not end up existing.) I think this should still be doable by just applying constraints to the right bindings, without snapshotting and merging, but it would require even more special-cased new APIs. Not sure it's worth it since this version already does so well, definitely no need to look into it now.
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.
Okay -- I'm going to move on for now as I think both of you have a far better understanding of our visibility constraints machinery than I do. But I welcome further optimisations of this code from anybody who wants to work on them 😄
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 sure it's worth it since this version already does so well, definitely no need to look into it now.
I agree. Seems like the new isolated application of constraints helps enough to simplify the overall constraint structure.
5730000
to
0bc6440
Compare
Summary
@sharkdp gets all the credit for this idea! Quoting his comments from Discord:
Test Plan
Existing tests all pass, and Codspeed is very happy about the PR!