Skip to content

Fix performance hang and OOM on conditional tuple appends#3744

Closed
QEDady wants to merge 2 commits into
facebook:mainfrom
QEDady:tuple-union-widening-limit
Closed

Fix performance hang and OOM on conditional tuple appends#3744
QEDady wants to merge 2 commits into
facebook:mainfrom
QEDady:tuple-union-widening-limit

Conversation

@QEDady

@QEDady QEDady commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a performance hang and Out-Of-Memory (OOM) error that occurs when type checking code with many conditional tuple appends (e.g. at control-flow joins).

Problem

At each control-flow join, Pyrefly computes the union of incoming types. For $N$ conditional tuple appends of distinct class types, this leads to an exponential combination of up to $2^N$ concrete tuple variants in the union. Pyrefly's simplifier stalls attempting to sort, deduplicate, and intersect this list, leading to $O(2^N)$ CPU time and OOM.

Solution

We introduce collapse_wide_tuple_unions during type simplification. If a union list contains more than a threshold of 8 tuple variants, they are collapsed/widened into a single unbounded tuple variant:
tuple[E, ...]
where E is the union of all element types recursively extracted from the constituent tuples (concrete, unbounded, or unpacked). This soundly bounds type complexity at control-flow joins to linear $O(N)$ complexity.

Fixes #3743

Test Plan

  1. Rust Unit Tests: Added test_collapse_wide_tuple_unions_corner_cases in simplify.rs to verify correct widening of concrete, unbounded, nested, unpacked, TypeVarTuple, and invalid fallback tuple combinations.
  2. Integration Regression Test: Added a 30-branch conditional tuple append integration test to test/basic.md using distinct class instances to ensure the widening threshold is properly triggered.
  3. Execution: Ran the tests
    python3 test.py 
  4. Performance Verification: Checked the 30-branch reproduction script on the local build. The run, which previously hung/timed out (exceeding 60 seconds at 100% CPU), now compiles successfully in 0.18 seconds with flat memory footprint (~360MB).

@yangdanny97

Copy link
Copy Markdown
Contributor

Nice, thanks

@github-actions github-actions Bot added size/l and removed size/l labels Jun 10, 2026
@meta-codesync

meta-codesync Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@yangdanny97 has imported this pull request. If you are a Meta employee, you can view this in D108143939.

@yangdanny97

Copy link
Copy Markdown
Contributor

FYI I'm gonna bump the limit to 64 here

@yangdanny97 yangdanny97 self-assigned this Jun 12, 2026
@yangdanny97

Copy link
Copy Markdown
Contributor

or rather, 256... pytorch has an un-annotated list of ~100 2-tuples :P

@samwgoldman samwgoldman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

@meta-codesync meta-codesync Bot closed this in 1c5d158 Jun 13, 2026
@meta-codesync meta-codesync Bot added the Merged label Jun 13, 2026
@meta-codesync

meta-codesync Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

@yangdanny97 merged this pull request in 1c5d158.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pyrefly hang / OOM during type checking of many conditional tuple appends

3 participants