Skip to content

[codex] optimize hot AST passes - #12

Merged
alvinwan merged 3 commits into
mainfrom
dev/alvin/optimize-speed-followup
Apr 5, 2026
Merged

[codex] optimize hot AST passes#12
alvinwan merged 3 commits into
mainfrom
dev/alvin/optimize-speed-followup

Conversation

@alvinwan

@alvinwan alvinwan commented Apr 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • speed up pymini's hottest AST passes without changing output size or semantics
  • cache profitability and scope-binding lookups used by public API preservation
  • avoid repeated subtree walks in repeated-name and repeated-string optimization passes
  • replace full-tree parent refreshes with local parent attachment for generated nodes
  • avoid linear mapping.values() scans and unnecessary generic_visit() calls on ast.Name
  • refresh the benchmark table with the latest results from this branch

Why

The previous speed pass fixed the largest structural regressions, but package-mode minification still spent a lot of time rewalking ASTs to recompute reserved names, scope bindings, and public-member profitability. This follow-up cuts those repeated walks while keeping compression rate and correctness intact.

Impact

Current benchmark results on this branch:

  • pyminifier.py: 1.5 ms
  • pyminify.py: 4.1 ms
  • TexSoup/*.py: 103.9 ms
  • TexSoup CLI package mode: 105.1 ms

Compared to the start of this branch:

  • pyminifier.py: 1.7 ms -> 1.5 ms
  • pyminify.py: 5.0 ms -> 4.1 ms
  • TexSoup/*.py: 162.1 ms -> 103.9 ms

Validation

  • PYTHONPATH=. .venv/bin/python -m pytest
  • PYTHONPATH=. .venv/bin/python scripts/regenerate_examples.py --check
  • PYTHONPATH=. .venv/bin/python -m pymini package /private/tmp/pymini-texsoup-repo/TexSoup -o /private/tmp/pymini-texsoup-testtarget
  • PYTHONPATH=/private/tmp/pymini-texsoup-testtarget:/private/tmp/pymini-texsoup-repo/tests .venv/bin/python -m pytest /private/tmp/pymini-texsoup-repo/tests -o addopts=''
  • PYTHONPATH=. .venv/bin/python benchmarks/benchmark_speed.py --pyminifier-root /private/tmp/pymini-pyminifier-src/pyminifier-2.1

@alvinwan
alvinwan marked this pull request as ready for review April 5, 2026 11:32
@alvinwan
alvinwan merged commit a685086 into main Apr 5, 2026
10 checks passed
@alvinwan
alvinwan deleted the dev/alvin/optimize-speed-followup branch April 5, 2026 11:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b015bb91ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pymini/pymini.py
Comment on lines +452 to +453
self.callable_argument_mappings[old_name] = copied
self.callable_argument_mappings[new_name] = copied

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Track argument mappings for callable aliases

When rename_arguments=True, argument rewrites are only registered for a function's original and renamed identifiers, so calls through aliases are missed. For example, alias = square; alias(long_value=3) is minified to a call that still uses long_value even though square's parameter was renamed, which raises TypeError at runtime. Alias assignments need to propagate the same callable-argument mapping to preserve keyword-call semantics.

Useful? React with 👍 / 👎.

Comment thread pymini/pymini.py
Comment on lines +475 to +476
if base_name in self.class_method_argument_mappings:
return self.class_method_argument_mappings[base_name].get(func.attr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve method keyword mappings on typed instances

The method keyword rewrite path only checks class contexts and direct class-name receivers, but it does not use instance bindings for obj.method(...) calls. With rename_arguments=True, code like m = Math(); m.square(long_value=3) keeps the old keyword after square's parameter is renamed, causing an unexpected-keyword TypeError in the minified output. The argument mapping lookup should also consult _lookup_instance_type(base_name) before giving up.

Useful? React with 👍 / 👎.

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.

1 participant