Repository navigation
Conversation
Lexer.read_name now finds the end of a name with one compiled regex match ([0-9A-Z_a-z]*, the same set that is_name_continue accepts) instead of a per-character Python loop. create_token and Token.__init__ store their values directly, without temporary locals or tuple packing. parse(large_query, no_location=True): 46.19 ms -> 41.43 ms (10.3%). Tokens, locations and errors stay the same. Co-Authored-By: Aiden <aiden@weco.ai>
Merging this PR will improve performance by 12.52%
Performance Changes
Tip Curious why performance improved? Comment Comparing |
The name pattern can match an empty string, so match() never returns None here. Mark the line for mypy instead of adding a runtime check. Co-Authored-By: Aiden <aiden@weco.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
parse(query, no_location=True).read_namenow uses one compiled regex match instead of a per-character loop.create_tokenandToken.__init__store their values directly, without temporary locals or tuple packing.test_parse_large_queryworkload, median wall time on one isolated core: 46.19 ms -> 41.43 ms, 10.3% faster.pytest testsgives 3821 passed, 18 skipped.Refs #306
What & Why
Before this change,
Lexer.read_namechecked every character of a name in a Python loop. Each step calledis_name_continue()and compared the position with the body length. Names are the most common tokens, so this loop used a large part of the parse time.Now the lexer compiles the regex
[0-9A-Z_a-z]*once per lexer and uses itsmatchto find where each name ends. This set is exactly whatis_name_continue()accepts: ASCII letters, digits and underscore. Thus every token keeps the same kind, start, end, line, column and value.create_tokenandToken.__init__compute the same values as before. They only skip temporary locals and tuple packing.Results
Median of several runs with CPython 3.12 on one isolated CPU core:
large_query.graphql,no_location=True(as intest_parse_large_query)github_schema.graphqlSDL,no_location=Truekitchen_sink.graphqlwith locations{ hello }A wider lexer workload measured 271.1 ms before and 245.1 ms after (about 10% less time, three repeats). It parses the large query, the kitchen sink with locations and full token streams.
Why this is safe and easy to maintain
The change is small: about 20 lines in two files, and each changed part is easy to read. The regex accepts the same characters as
is_name_continue(), so tokens and errors do not change. The lexer, parser and AST tests intests/languagecover this code.Validation
pytest tests: 3821 passed, 18 skipped.pytest tests/language: 409 passed, 1 skipped.ruff checkandruff format --checkpass on the two changed files.pytest tests/benchmarks/test_serialization.py -k parse_large_query.AI assistance
The code change was found with automated tooling: OpenAI Codex (gpt-6.1-sol) proposed the candidates, and Weco Observe tracked them. An automated agent picked the candidate, ran the tests and did the timing. No human review has happened yet.
Weco share link: https://dashboard.weco.ai/share/FRl_naVP6T86RC8_gUDY6lGUHpnbABkm