Skip to content

Speed up identifier and keyword lexing - #29463

Merged
charliermarsh merged 9 commits into
mainfrom
charlie/ruff-ascii-identifiers
Oct 23, 2026
Merged

charliermarsh merged 9 commits into
mainfrom
charlie/ruff-ascii-identifiers

Conversation

@charliermarsh

@charliermarsh charliermarsh commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Summary

We scan ASCII identifier continuations in sixteen-byte batches using a byte lookup table, avoiding per-character decoding. Keyword lookup filters by length and initial byte, then uses a compact hash table with a full-word comparison to reject collisions. Non-ASCII suffixes retain the existing Unicode path.

@charliermarsh charliermarsh added performance Potential performance improvement parser Related to the parser labels Oct 18, 2026
@astral-sh-bot

astral-sh-bot Bot commented Oct 18, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged βœ…

@astral-sh-bot

astral-sh-bot Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected βœ…

Full report with detailed diff (timing results)

@charliermarsh charliermarsh changed the title Scan ASCII identifiers with byte lookups Batch ASCII identifier scanning Oct 18, 2026
@astral-sh-bot

astral-sh-bot Bot commented Oct 18, 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 Oct 19, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 4.86%

1 warning

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

⚑ 3 improved benchmarks
βœ… 259 untouched benchmarks
⏩ 14 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚑ CPU Simulation lexer[numpy/globals.py] 41.6 ¡s 39.5 ¡s +5.38%
⚑ CPU Simulation lexer[pydantic/types.py] 682.6 ¡s 649.9 ¡s +5.03%
⚑ CPU Simulation lexer[numpy/ctypeslib.py] 302.1 ¡s 290 ¡s +4.17%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing charlie/ruff-ascii-identifiers (6818c90) with main (5fabb6f)

Open in CodSpeed

Footnotes

  1. 14 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. ↩

@charliermarsh charliermarsh changed the title Batch ASCII identifier scanning Speed up identifier and keyword lexing Oct 19, 2026
@charliermarsh
charliermarsh changed the base branch from main to charlie/ruff-shared-postfix-atom October 19, 2026 14:02
@charliermarsh
charliermarsh force-pushed the charlie/ruff-ascii-identifiers branch from a1177bd to f91d049 Compare October 19, 2026 14:02
@charliermarsh
charliermarsh force-pushed the charlie/ruff-ascii-identifiers branch from ea02032 to d47bd15 Compare October 19, 2026 15:11
Base automatically changed from charlie/ruff-shared-postfix-atom to main October 19, 2026 20:35
@charliermarsh
charliermarsh force-pushed the charlie/ruff-ascii-identifiers branch from d47bd15 to 03bf69f Compare October 19, 2026 20:35
@charliermarsh
charliermarsh marked this pull request as ready for review October 19, 2026 21:05
@MichaReiser

Copy link
Copy Markdown
Member

why?

@charliermarsh

Copy link
Copy Markdown
Member Author

I got the vibe from your comments that you didn't want to proceed with it haha! Do you think it's salvageable? I'm happy to clean it up, I just thought you were left feeling like the tradeoffs weren't right.

@MichaReiser

MichaReiser commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

I think it's a worthwhile change. I just think it requires some more explanation of what happens here and how to update that weird constant when adding/removing kewyords πŸ˜†

@charliermarsh

Copy link
Copy Markdown
Member Author

Haha ok. I will clean it up. I'll ask Codex to make it even weirder and more confusing.

# dependencies = []
# ///

"""Generate the lexer's keyword table and collision-free hash multiplier.

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.

How is this different from using phf?

@charliermarsh charliermarsh Oct 23, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So, I tried phf::Map, but it seems like it's meaningfully slower because phf still runs SipHash (the main benefit seems to be that it guarantees you don't have collisions?) but these can just fit in a u64.

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

Thank you. This makes sense to me. The only part that isn't clear to me (and might be worth documenting), is why we can't use pfh. I'd prefer that over a custom Python script that generates the lookup table.

@charliermarsh
charliermarsh force-pushed the charlie/ruff-ascii-identifiers branch from 6e5b67b to 6818c90 Compare October 23, 2026 17:45
@astral-automations-bot

Copy link
Copy Markdown
Contributor

Memory usage report

Memory usage unchanged βœ…


Results for 6818c90 Β· Workflow run

@astral-automations-bot

Copy link
Copy Markdown
Contributor

ecosystem-analyzer results

No diagnostic changes detected βœ…

Full report with detailed diff Β· Timing results


Results for 6818c90 Β· Workflow run

@charliermarsh
charliermarsh merged commit de9d86e into main Oct 23, 2026
77 checks passed
@charliermarsh
charliermarsh deleted the charlie/ruff-ascii-identifiers branch October 23, 2026 17:58
charliermarsh added a commit that referenced this pull request Oct 23, 2026
## Summary

We give ASCII identifiers a dedicated path, avoiding Unicode bookkeeping
and checking string prefixes only when a one- or two-letter name reaches
a quote. Both paths share the existing batched ASCII scanner, preserving
fast scanning for Unicode names with long ASCII suffixes.

Stacked on #29463 to measure the incremental improvement. [CodSpeed
reports](https://github.com/astral-sh/ruff/pull/29503/checks?check_run_id=118300735426)
6.6–9.8% greater efficiency across all five lexer benchmarks, with no
reported regressions. We preserve the existing scanner and add no
inlining attributes or unsafe code.
rlichtenwalter added a commit to rlichtenwalter/dir2text that referenced this pull request Oct 30, 2026
This PR contains the following updates:

| Package | Type | Update | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [DavidAnson/markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) | repository | minor | `v0.23.3` β†’ `v0.24.0` | ![age](https://developer.mend.io/api/mc/badges/age/github-tags/DavidAnson%2fmarkdownlint-cli2/v0.24.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/DavidAnson%2fmarkdownlint-cli2/v0.23.3/v0.24.0?slim=true) |
| [ruff](https://docs.astral.sh/ruff) ([source](https://github.com/astral-sh/ruff), [changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)) | dependency-groups | patch | `==0.17.1` β†’ `==0.17.3` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.17.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.17.1/0.17.3?slim=true) |

Note: The `pre-commit` manager in Renovate is not supported by the `pre-commit` maintainers or community. Please do not report any problems there, instead [create a Discussion in the Renovate repository](https://github.com/renovatebot/renovate/discussions/new) if you have any questions.

---

### Release Notes

<details>
<summary>DavidAnson/markdownlint-cli2</summary>

### [`v0.24.0`](DavidAnson/markdownlint-cli2@v0.23.3...v0.24.0)

[Compare Source](DavidAnson/markdownlint-cli2@v0.23.3...v0.24.0)

</details>

<details>
<summary>astral-sh/ruff (ruff)</summary>

### [`v0.17.3`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#0173)

[Compare Source](astral-sh/ruff@0.17.2...0.17.3)

Released on 2026-10-26.

##### Preview features

- \[`suspicious`] Add `shared-clock-mock` ([#&#8203;29074](astral-sh/ruff#29074))

##### Bug fixes

- \[`pyupgrade`] Avoid incorrect conversions to f-strings (`UP032`) ([#&#8203;25485](astral-sh/ruff#25485))

##### Performance

- Buffer stdout in `ruff format` ([#&#8203;29631](astral-sh/ruff#29631))
- Specialize ASCII identifier lexing ([#&#8203;29503](astral-sh/ruff#29503))
- Speed up identifier and keyword lexing ([#&#8203;29463](astral-sh/ruff#29463))

##### Documentation

- \[`flake8-bandit`] Describe what the rule actually checks for `httpx` (`S113`) ([#&#8203;27936](astral-sh/ruff#27936))

##### Contributors

- [@&#8203;itsvedantkumar](https://github.com/itsvedantkumar)
- [@&#8203;charliermarsh](https://github.com/charliermarsh)
- [@&#8203;anishgirianish](https://github.com/anishgirianish)

### [`v0.17.2`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#0172)

[Compare Source](astral-sh/ruff@0.17.1...0.17.2)

Released on 2026-10-22.

##### Preview features

- \[`complexity`] Add `unnecessary-regular-expression-compile` ([#&#8203;25533](astral-sh/ruff#25533))

##### Bug fixes

- Avoid syntax errors for type variables with starred constraints (`UP040`, `UP046`, `UP047`, `RUF053`) ([#&#8203;28362](astral-sh/ruff#28362))
- \[`pydocstyle`] Treat backslash-escaped `*args` and `**kwargs` as documented (`D417`) ([#&#8203;29536](astral-sh/ruff#29536))
- \[`pylint`] Avoid false positive on starred elements (`PLE0643`) ([#&#8203;29483](astral-sh/ruff#29483))
- \[`pylint`] Mark fixes unsafe when deleting comments (`PLR5501`, `PLW0120`) ([#&#8203;29414](astral-sh/ruff#29414))
- \[`pyupgrade`] Mark fix unsafe when deleting comments (`UP035`) ([#&#8203;29413](astral-sh/ruff#29413))

##### Performance

- Avoid intermediate names in lint name resolution ([#&#8203;29506](astral-sh/ruff#29506))
- Prefilter bidirectional Unicode checks by UTF-8 leading bytes ([#&#8203;29561](astral-sh/ruff#29561))
- Share postfix parsing and reduce expression copies ([#&#8203;29480](astral-sh/ruff#29480))

##### Configuration

- \[`pylint`] Add a configurable allowlist for `magic-value-comparison` (`PLR2004`) ([#&#8203;18961](astral-sh/ruff#18961))

##### Documentation

- Clarify documentation and correct stale guidance ([#&#8203;29374](astral-sh/ruff#29374))
- \[`pyupgrade`] Remove mentions of variance related to fix safety (`UP040`, `UP047`) ([#&#8203;29592](astral-sh/ruff#29592))

##### Contributors

- [@&#8203;fixfon](https://github.com/fixfon)
- [@&#8203;MichaReiser](https://github.com/MichaReiser)
- [@&#8203;zaniebot](https://github.com/zaniebot)
- [@&#8203;FrancescoPezzella](https://github.com/FrancescoPezzella)
- [@&#8203;anishgirianish](https://github.com/anishgirianish)
- [@&#8203;rajveer3x](https://github.com/rajveer3x)
- [@&#8203;charliermarsh](https://github.com/charliermarsh)
- [@&#8203;LckyLike](https://github.com/LckyLke)
- [@&#8203;DaniBodor](https://github.com/DaniBodor)

</details>

---

### Configuration

πŸ“… **Schedule**: (in timezone America/Denver)

- Branch creation
  - Between 02:00 AM and 06:59 AM, only on Tuesday (`* 2-6 * * 2`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

β™» **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

πŸ‘» **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNDguMyIsInVwZGF0ZWRJblZlciI6IjQ0LjE0OC4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->

Reviewed-on: https://git.lichtenwalter.site/rlichten/dir2text/pulls/100

This branch was previously deployed

1 inactive deployment
automations β€” 6818c903 Deployed Oct 23, 2026 by charliermarsh via security-review / security review #93186
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parser Related to the parser performance Potential performance improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants