Conversation
| } | ||
|
|
||
| if context.cyclic { | ||
| for mixin in mixins { |
There was a problem hiding this comment.
Here instead of looping through the mixins, I think we can add the circular dependency diagnostic directly in linearize_ancestors when we conclude that it's a cyclic dependency here:
rubydex/rust/rubydex/src/resolution.rs
Line 642 in 6b6d1e0
That way, we automatically add diagnostics for cyclic parent classes too.
There was a problem hiding this comment.
I don't think we can do it here without some involved refactoring as we're missing the information we need to attach the diagnostic to the proper place. At this stage, we don't know if the conflict comes from a parent class or a mixin.
There was a problem hiding this comment.
Yes, indeed. I think we can change the seen from a HashSet to a HashMap, where the keys are still the declaration IDs and the values are the information you need to add the diagnostic at the right place.
That way we can avoid looping through the mixins again.
I think that will also solve the parent class cyclic check and simplify the code. We can do that in a separate PR though.
|
|
||
| let result = self.linearize_ancestors(picked_parent, context); | ||
|
|
||
| if matches!(result, Ancestors::Cyclic(_)) |
There was a problem hiding this comment.
This can go away if we move the diagnostic to that spot in linearize_ancestors.
529e109 to
7b12c21
Compare
|
Just to compare I removed the cyclic checks and ran the numbers again: So even with moving the cyclic checks inline we're not faster than #474. |
rust/rubydex/src/resolution.rs
Outdated
| } | ||
| Outcome::Unresolved(None) => { | ||
| // We couldn't resolve this name. Emit a diagnostic | ||
| unit_queue.push_back(unit_id); |
There was a problem hiding this comment.
Just for information, I commented this on Thomas' PR too: there's a bit of a mistake here. The original reason I separated Retry from Unresolved is to avoid retrying constants that we know for sure are undefined (i.e.: we had all of its dependencies, but still failed to resolve it).
I think we need a list separate from the unit queue for unresolved constants so that we can avoid retrying these.
At the end of the loop, unresolved constants will be the concatenation of the unresolved constants (things we were sure we couldn't resolve) + whatever is left in the queue (stuff we retried, but still failed to resolve).
We can address this in a separate PR, but let's please leave a TODO, so that we don't forget. This will increase the number of retries.
| .map(|mixins| mixins.into_iter().map(|mixin| (mixin, *definition_id))) | ||
| }) | ||
| .flatten() | ||
| .collect::<Vec<(Mixin, DefinitionId)>>(); |
There was a problem hiding this comment.
This is now producing an extra intermediate vector, whereas the code before was extending from an iterator.
Are we able to revert to the original?
| .map(|mixins| mixins.into_iter().map(|mixin| (mixin, *definition_id))) | ||
| }) | ||
| .flatten() | ||
| .collect::<Vec<(Mixin, DefinitionId)>>(); |
| } | ||
|
|
||
| if context.cyclic { | ||
| for mixin in mixins { |
There was a problem hiding this comment.
Yes, indeed. I think we can change the seen from a HashSet to a HashMap, where the keys are still the declaration IDs and the values are the information you need to add the diagnostic at the right place.
That way we can avoid looping through the mixins again.
I think that will also solve the parent class cyclic check and simplify the code. We can do that in a separate PR though.
Step towards #141 When thinking about using u32 IDs, I was getting really caught up by the fact that Rust's `HashMap` implementation still requires storing a u64 for the key digests. Of course that consumes more memory and ideally we can have a custom `HashMap` implementation that uses half the amount of bits. However, we actually use IDs quite extensively outside of just `HashMap` keys. For example, many definitions store StringId, names store multiple NameIds and ancestors is a list of DeclarationId. We can actually have very substantial memory savings right now even without the 32 bit `HashMap`. ### Implementation This PR reduces the size of our IDs to u32 from i64. I recommend reviewing per commit: 1. Reduce the ID size to u32 2. Allow `DefinitionId` and `ReferenceId` to be tagged with their kind. This helps us reduce the changes of collision by encoding the kind in the lower bits of the ID. Essentially, we have 28 bits for the digest + 4 for the kind. Definitions and references are the things we have the most in Core and the only ones I got conflicts for running the release mode, so I think this is enough for the time being. As an added benefit, this allows to check the kind of definitions and references without having to retrieve them from the graph. That information is directly encoded in the ID, we can just invoke `kind`. Note that the `kind` addition conflicts with #502, we can let that PR go first. 3. Adjust the C side to use u32 ### Impact Despite still using 64 bit `HashMaps`, this PR still reduces our memory used from `~3810 MB` to `~2880 MB` (25% reduction). I believe we can further reduce this with a custom `HashMap` implementation that stores u32 internally. ### Why now? I believe this is the right time to do this for the following reason: we're starting adoption of Rubydex in our tools. It will be easier for us to verify that we can indeed get away with u32 and lower memory usage _and then_ increase to u64 if necessary than the other way around. Also, we're almost getting to 4GB and a reduction is definitely welcome.
7b12c21 to
47c9266
Compare
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
14a82d7 to
e44d719
Compare
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
e44d719 to
314f593
Compare
Same than #474 but resolution diagnostics are pushed during the resolution rather than after.
Inline validation appears to be slightly slower, though I think we're in the noise at this point.
^ @vinistock