Skip to content

perf(transform): O(1) class-chain lookups in inliner shadowing analysis#5082

Merged
proggeramlug merged 1 commit into
mainfrom
perf/inline-class-chain-lookup
Jun 13, 2026
Merged

perf(transform): O(1) class-chain lookups in inliner shadowing analysis#5082
proggeramlug merged 1 commit into
mainfrom
perf/inline-class-chain-lookup

Conversation

@TheHypnoo

@TheHypnoo TheHypnoo commented Jun 13, 2026

Copy link
Copy Markdown
Member

Replaces the O(classes) linear scan per inheritance level in the inliner's method-shadowing analysis with O(1) hash lookups.

What

method_lookup_is_unshadowed and class_chain_property_sets (crates/perry-transform/src/inline/analysis.rs) walk the class inheritance chain (depth capped at 32) and at every level did classes.iter().find(|c| c.name == name) — an O(number-of-classes) scan. Both functions are called once per inlinable-method candidate (from inline/mod.rs and inline/cross_module.rs), so candidate evaluation was effectively O(candidates × depth × classes). On modules with many classes and deep hierarchies (e.g. Effect-style codebases) this is wasted compile time.

This indexes the class slice by name into a HashMap<&str, &Class> once per call and does O(1) lookups during the walk.

Correctness

HashMap::entry(...).or_insert(c) keeps the first class for a duplicate name, exactly matching the prior iter().find() first-match semantics. This matters: duplicate class names occur across modules (e.g. Effect's same-named Type in SchemaAST and ParseResult). Compiler output is unchanged — only lookup complexity drops.

Verification

  • cargo test --release -p perry-transform — all pass (30 tests).
  • Built the full driver and compiled/ran a 3-level inheritance program with method overriding and inlining; output is correct (overrides resolve to the right method, inherited methods reach the base implementation).

Pure compile-speed change; no runtime or codegen-output behavior change.

Summary by CodeRabbit

  • Refactor
    • Optimized class name resolution in method-lookup and property-set validation checks for improved performance.

method_lookup_is_unshadowed and class_chain_property_sets walked the class
inheritance chain with an O(classes) linear scan per level
(classes.iter().find()), making method-inlining candidate evaluation
O(candidates * depth * classes) on deep hierarchies.

Index classes by name once into a HashMap (entry().or_insert keeps the first
class for a duplicate name, preserving the prior iter().find() first-match
semantics — duplicate class names occur cross-module). Output is unchanged;
only the lookup complexity drops to O(1) per chain level.
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cfdef94f-be66-469b-84a2-7bb904c08748

📥 Commits

Reviewing files that changed from the base of the PR and between 06caf3d and b0a8617.

📒 Files selected for processing (1)
  • crates/perry-transform/src/inline/analysis.rs

📝 Walkthrough

Walkthrough

This PR optimizes class-lookup performance in the inline analysis module by replacing repeated linear searches over class lists with pre-built HashMap indices keyed by class name. Both method_lookup_is_unshadowed and class_chain_property_sets now build and use an indexed map during prototype-chain walks to resolve classes in constant time rather than linear time.

Changes

Inline Analysis Class Lookup Optimization

Layer / File(s) Summary
Hash-based class lookup in analysis functions
crates/perry-transform/src/inline/analysis.rs
method_lookup_is_unshadowed and class_chain_property_sets replace per-step linear searches with a pre-built HashMap indexed by class name, using entry(...).or_insert(...) to preserve "first duplicate" semantics and get() for O(1) lookups during prototype-chain walks.

🎯 1 (Trivial) | ⏱️ ~5 minutes

🐰 A rabbit hops with glee,
Hash maps now, no more linear spree!
Class lookups swift and bright,
Prototype chains run right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: performance optimization of class-chain lookups from linear to O(1) hash lookups in the inliner's shadowing analysis.
Description check ✅ Passed The description is comprehensive and follows the template structure with clear Summary, What, Correctness, and Verification sections covering all essential aspects of the change.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/inline-class-chain-lookup

Comment @coderabbitai help to get the list of available commands and usage tips.

@proggeramlug proggeramlug merged commit a8ac153 into main Jun 13, 2026
14 checks passed
@proggeramlug proggeramlug deleted the perf/inline-class-chain-lookup branch June 13, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants