Skip to content

Memory Optimizations#5222

Open
rsb-23 wants to merge 5 commits into
psf:mainfrom
rsb-23:main
Open

Memory Optimizations#5222
rsb-23 wants to merge 5 commits into
psf:mainfrom
rsb-23:main

Conversation

@rsb-23

@rsb-23 rsb-23 commented Jul 4, 2026

Copy link
Copy Markdown

Description

Reference : issue #5216

  1. Reduces per-instance memory of Node and Leaf (the two most frequently instantiated objects;
    every token and AST node in a formatted file is one of these)
    and cuts allocation overhead across the hot formatting path.
  2. Removed dead fields (used_names and fixers_applied), never read anywhere.
  3. Simplified unnecessary string and other object creations to reduce memory allocations.
  4. Removed avoidable intermediate allocations in hot paths like r = r0 | r1

Measured on a synthetic benchmark: peak memory 75.325 MB → 20.107 MB after these changes.

Checklist - did you ...

  • Implement any code style changes under the --preview style, following the stability policy?
  • Add an entry in CHANGES.md if necessary?
  • Add / update tests if necessary?
  • Add new / update outdated documentation?

rsb-23 added 2 commits July 5, 2026 03:16
- removed dead fields and redundant vars
- removed unused import
@cobaltt7 cobaltt7 linked an issue Jul 5, 2026 that may be closed by this pull request

@cobaltt7 cobaltt7 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks! Could you add a high-level changelog entry for one or two of the biggest changes?

Comment thread src/blib2to3/pytree.py
Comment thread src/blib2to3/pytree.py Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this argument now unused?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, fixer_applied is now unused in both Node and Leaf. But since Node had unused 'context' param, so I kept this param as is.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you remove both while we're here? I imagine unused variables would also contribute to high memory usage?

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

diff-shades results comparing this PR (f2c7b3e) to main (d7587ce):

--preview style: no changes

--stable style: no changes


What is this? | Workflow run | diff-shades documentation

@tusharsadhwani

Copy link
Copy Markdown
Collaborator

Did you compare this under the mypyc build? slots shouldn't make that big of a difference after being compiled

@JelleZijlstra JelleZijlstra left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This makes a lot of stylistic changes, many of which are unlikely to affect memory usage.

You claim this reduced memory usage significantly. How did you measure this? Did you compile Black with mypyc? And which specific changes can be proven to help?

Comment thread src/black/brackets.py Outdated
Comment thread src/black/handle_ipynb_magics.py Outdated
Comment thread src/black/handle_ipynb_magics.py Outdated
Comment thread src/black/lines.py Outdated
Comment thread src/black/lines.py Outdated
comments_iter = itertools.chain.from_iterable(self.comments.values())
comments = [str(comment) for comment in comments_iter]
res += "".join(comments)
first, *rest = self.leaves

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The new code overall seems nicer here but note this materializes rest into a new list and therefore might use more memory.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks to point it out.
Since self.leaves is already a list, hence now using it directly instead of creating iter overhead.

Comment thread src/black/output.py
Comment thread src/black/trans.py Outdated
group of custom splits.
"""
return (id(string), string)
return id(string), string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This definitely doesn't affect memory usage.

Comment thread src/black/trans.py
for start, end in iter_fexpr_spans(fstring):
parts.append(fstring[previous_index:start])
parts.append(fstring[start:end].replace(old_quote, new_quote))
parts.extend((

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

old code is better

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We're unlikely to accept a big change that's just your personal style preferences.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not a style preference, but a micro-optimization.
Reason is as for 'output.py' changes.

Comment thread src/blib2to3/pgen2/conv.py Outdated
Comment thread src/blib2to3/pytree.py


class Base:
class Base(ABC):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Making this an ABC may well have negative performance effects.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

There is non-negative effect indicated in stats below.
mypyc ABC support

@rsb-23

rsb-23 commented Jul 5, 2026

Copy link
Copy Markdown
Author

@tusharsadhwani @JelleZijlstra
I have used the default build, I will confirm for mypyc.

I took few of the slow testcases to profile for memory and check hot classes.
Here is 1 of the profiler scripts memory_profier.py

@rsb-23

rsb-23 commented Jul 10, 2026

Copy link
Copy Markdown
Author

These results are based on the profiler script memory_profier.py
OS: Linux
Python: 3.12

Performance (Negligible)

Build Pure Python mypyc
Upstream 21.6s 14.4s
This PR 21.0s 13.6s

Memory

Slight improvement in mypyc build, while Pure python is much better

Current \ Peak allocations (in MB)

Build Pure Python mypyc
Upstream 12.174 \ 41.601 9.538 \ 25.711
This PR 1.481 \ 20.075 7.157 \ 24.568

- Added comments and Changelog
- reverted additional changes
- reverted micro optims
@rsb-23
rsb-23 requested a review from JelleZijlstra July 13, 2026 15:03
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.

Potential memory optimizations

4 participants