Skip to content

[ty] Reduce Expr size to 64 bytes - #27591

Merged
charliermarsh merged 7 commits into
mainfrom
charlie/codex-ty-ast-memory
Aug 9, 2026
Merged

charliermarsh merged 7 commits into
mainfrom
charlie/codex-ty-ast-memory

Conversation

@charliermarsh

@charliermarsh charliermarsh commented Aug 8, 2026 •

Copy link
Copy Markdown
Member

Summary

This PR reduces the size of Expr from 72 to 64 bytes by storing only the start offset on ExprCall (64 to 56 bytes) and boxing the uncommon implicitly concatenated string representation in ExprStringLiteral (64 to 48 bytes). Both changes are required to reduce the size of the containing Expr enum.

ExprCall derives its end offset from its argument list; parser and error-recovery paths assert that their ranges share the same end.

@charliermarsh charliermarsh added the ty The ty type checker label Aug 8, 2026 — with ChatGPT Codex Connector
@astral-sh-bot

astral-sh-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 96.96%. The percentage of expected errors that received a diagnostic held steady at 92.96%. The number of fully passing files held steady at 106/133.

@astral-sh-bot

astral-sh-bot Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
flake8 40.38MB 39.66MB -1.80% (746.39kB) ⬇️
trio 93.28MB 92.20MB -1.15% (1.07MB) ⬇️
sphinx 164.92MB 163.24MB -1.02% (1.68MB) ⬇️
prefect 453.68MB 449.37MB -0.95% (4.31MB) ⬇️

Significant changes

Click to expand detailed breakdown

flake8

Name Old New Diff Outcome
parsed_module 15.50MB 14.77MB -4.70% (746.39kB) ⬇️

trio

Name Old New Diff Outcome
parsed_module 23.25MB 22.18MB -4.62% (1.07MB) ⬇️

sphinx

Name Old New Diff Outcome
parsed_module 34.30MB 32.62MB -4.90% (1.68MB) ⬇️

prefect

Name Old New Diff Outcome
parsed_module 89.10MB 84.79MB -4.84% (4.31MB) ⬇️

@astral-sh-bot

astral-sh-bot Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Full report with detailed diff (timing results)

@astral-sh-bot

astral-sh-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@codspeed

codspeed Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 5.62%

⚡ 4 improved benchmarks
✅ 167 untouched benchmarks
⏩ 24 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚡ Memory parser[large/dataset.py] 727.7 KB 682.7 KB +6.6%
⚡ Memory parser[unicode/pypinyin.py] 48.9 KB 46.3 KB +5.65%
⚡ Memory parser[pydantic/types.py] 312.8 KB 296.8 KB +5.38%
⚡ Memory parser[numpy/ctypeslib.py] 147.3 KB 140.4 KB +4.85%

Tip

Curious why this is faster? Use the CodSpeed MCP and ask your agent.


Comparing charlie/codex-ty-ast-memory (333767b) with main (4f312d3)

Open in CodSpeed

Footnotes

  1. 24 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@MichaReiser

MichaReiser commented Aug 8, 2026 •

Copy link
Copy Markdown
Member

Can we split the optimization into separate PRs, or are all of those needed to reduce the size?

I also think that this will soon matter less, once we have proper eviction for parsed module. So I'd suggest we focus on the perf improvement (which is nice!)

@charliermarsh

Copy link
Copy Markdown
Member Author

I think the CodSpeed "perf improvement" is all memory though, right? :D

@charliermarsh
charliermarsh force-pushed the charlie/codex-ty-ast-memory branch from 559c623 to 9e37e7a Compare August 8, 2026 17:37
@charliermarsh charliermarsh changed the title [ty] Reduce retained memory for parsed modules [ty] Reduce expression AST size Aug 8, 2026
@charliermarsh
charliermarsh marked this pull request as ready for review August 8, 2026 17:52
@charliermarsh charliermarsh added performance Potential performance improvement and removed ty The ty type checker labels Aug 8, 2026
@charliermarsh charliermarsh changed the title [ty] Reduce expression AST size Reduce expression AST size Aug 8, 2026
@charliermarsh

Copy link
Copy Markdown
Member Author

(Carved out the other changes but then decided they weren't worth it so this just reduces expression size.)

@charliermarsh
charliermarsh requested a review from a team as a code owner August 8, 2026 18:06
@charliermarsh charliermarsh changed the title Reduce expression AST size [ty] Reduce Python AST memory usage Aug 8, 2026
@charliermarsh charliermarsh changed the title [ty] Reduce Python AST memory usage [ty] Reduce Expr size to 64 bytes Aug 8, 2026

@MichaReiser MichaReiser 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.

I'd prefer if we split the changes unrelated to reducing the size of Expr into their own PR. I want to see the memory usage/perf results for those separately to get a better sense on if the error recovery trade offs are justified.

func: Box::new(func),
arguments,
range: self.node_range(start),
range_start: start,

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.

Can we add some debug assertions here and in other places in the parser, asserting that self.node_range(start) == arguments.end()

Comment thread crates/ruff_python_ast/src/nodes.rs Outdated
#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
pub struct Alias {
pub range: TextRange,
pub range_end: TextSize,

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.

We should document the assumption that name.start() == alias.start() here (somewhere). Because it has implications on the parsers error recovery, that make me a feel a little uneasy (just something more that we have to think about in the already complex recovery). We should document the same for other nodes where we now apply this optimization.

Specifically, the parser is not allowed to perform any error recovery between alias.start() and parsing name. Because any bumped token between start and name (even if only for error recovery), would violate the name.start() == alias.start() constraints.

Given this, I'd prefer if we only make this optimization for nodes where there's a very clear benefit. E.g. reducing Expr to 64 bytes seems meaningful. I'm not convinced the tradeoff for Alias are given (also, changing Alias doesn't fit the PR description, so I'd suggest we move this optimization out of this PR).

@MichaReiser MichaReiser added parser Related to the parser memory An issue regarding poor memory usage, or a PR improving memory usage and removed performance Potential performance improvement labels Aug 9, 2026
@charliermarsh
charliermarsh enabled auto-merge (squash) August 9, 2026 13:37
@charliermarsh
charliermarsh merged commit c56aad1 into main Aug 9, 2026
63 checks passed
@charliermarsh
charliermarsh deleted the charlie/codex-ty-ast-memory branch August 9, 2026 13:41
George-Ogden pushed a commit to George-Ogden/ruff that referenced this pull request Aug 16, 2026
## Summary

This PR reduces the size of `Expr` from 72 to 64 bytes by storing only
the start offset on `ExprCall` (64 to 56 bytes) and boxing the uncommon
implicitly concatenated string representation in `ExprStringLiteral` (64
to 48 bytes). Both changes are required to reduce the size of the
containing `Expr` enum.

`ExprCall` derives its end offset from its argument list; parser and
error-recovery paths assert that their ranges share the same end.

---------

Co-authored-by: Charlie Marsh <charliemarsh@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

memory An issue regarding poor memory usage, or a PR improving memory usage parser Related to the parser

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants