* main:
[ty] Move binary expression logic out of `builder.rs` (#23649)
[ty] Limit recursion depth when displaying self-referential function types (#23647)
[ty] Move comparison logic out of `builder.rs` (#23646)
Avoid inserting redundant `None` elements in UP045 (#23459)
[ty] Add more ParamSpec validation for `P.args` and `P.kwargs` (#23640)
[ty] Sync vendored typeshed stubs (#23642)
[ty] Fix inference of `t.__mro__` if `t` is an instance of `type[Any]` (#23632)
[ty] Detect inconsistent generic base class specializations (#23615)
[ty] Validate type variable defaults don't reference later type parameters or type parameters out of scope (#23623)
[ty] Ban nested `Required`/`NotRequired`, and ban them both outside of `TypedDict` fields (#23627)
[ty] Reject generic metaclasses parameterized by type variables (#23628)
Update default Python version examples (#23605)
fix binops with NewType of float and Unknown (#23620)
[ty] Reject functions with PEP-695 type parameters that shadow type parameters from enclosing scopes (#23619)
[ty] Reject ellipsis literals in odd places in type/annotation expressions (#23611)
[ty] hash-cons `UseDefMap` fields (#23283)
Summary
Implement hash-consing for several fields in
UseDefMapto reduce memory usage.The rationale for this optimization is the size and high duplication rate of the structs used in
UseDefMap. The size of each struct is:These elements are stored within
IndexVecwhere duplication of elements can occur.For example, taking these statistics (duplication rate) with hydra-zen yields the following:
The disparity in duplication rates between symbols and members was a bit surprising, but can be explained as follows:
obj.attrandobj["k"]might be tracked, but often end up in a similar undefined/unbound state, leading to a large number of identicalPlaceStateinstances.This PR implements hash-consing for these fields. Specifically, each
IndexVecfor these fields will only store IDs for each struct, and the actual struct instances will be stored in anotherIndexVecwithout duplication.According to the memory usage report, this change reduced the size of
SemanticIndexby about 10%.Performance analysis
What this PR is trying to do involves a trade-off between time complexity and space complexity.
In #23201, I aimed to achieve a more significant reduction in memory consumption by interning
Bindings, but this resulted in a major regression in time performance, so I decided to manually intern only items that seemed to have a high effect.This PR change is not very effective for microbenchmarks, and rather adds a time cost (due to hash calculations). However, looking at the trends in the memory report, it seems that for large codebases, it can achieve significant memory savings with relatively little overhead. The larger the
UseDefMap, the greater the reduction, so I think it's worth to do this.The commit that achieved the greatest memory consumption reduction in this PR was b9d067a, but it was reverted because it exceeded the threshold for codspeed microbenchmarks. There was almost no impact on walltime benchmarks (in fact, some even showed slight improvements).
Test Plan
N/A