Skip to content

assert_name checks each character in a Python generator #304

Open

Description

@dexhunter

assert_name() in src/graphql/type/assert_name.py runs for every type, field, argument and enum value name when a schema is built.
It checks the name tail with all(is_name_continue(char) for char in name[1:]).
This runs one Python function call for each character.

For a schema of the GitHub size, this check uses about one quarter of the build time.

Situation Now With the proposed fix Change
build_ast_schema on the GitHub SDL (assume_valid=True) 14.40 ms 10.79 ms 25.0% less time
build_client_schema on the GitHub introspection result 13.97 ms 10.43 ms 25.3% less time
assert_name on 10,000 valid names 6.94 ms 0.69 ms 90.0% less time
assert_name on 10,000 invalid names 13.32 ms 8.62 ms 35.3% less time
parse on the large query (does not call assert_name) 38.43 ms 37.90 ms No change (within noise)

These are the best of 15 runs, median of 7 alternating processes per version.

Proposed fix: for an ASCII string, str.isidentifier() is true exactly for [_a-zA-Z][_a-zA-Z0-9]*.
Use name.isascii() and name.isidentifier() to return valid names early, and keep the current error checks and messages for invalid names.

Environment: CPython 3.12.13, Linux x86-64, AMD EPYC 9R14, graphql-core main at 0aaea71.

Activity

  1. swayamdudhela commented on Nov 7, 2026

    @swayamdudhela

    Hi! I'd like to contribute to this issue.

    I understand that the goal is to optimize the assert_name validation check while preserving the existing validation behaviour.

    I'd like to inspect the current implementation, identify a safe optimization, and add or update tests to ensure that valid and invalid GraphQL names continue to behave correctly.

    Would this issue be available for an external contributor? I'd be happy to work on it if the maintainers are open to assigning it.

    Thanks!

  2. dexhunter commented on Nov 7, 2026

    @dexhunter
    ContributorAuthor

    For context, PR #305 already has a fix for this issue. It is open and waits for maintainer review.

    The fix changes only assert_name() in src/graphql/type/assert_name.py. Valid names return early with name.isascii() and name.isidentifier(). Invalid names keep the same checks and error messages.

    The PR includes the full test run and before/after benchmarks. Review comments on #305 are welcome.

  3. Cito commented on Nov 7, 2026

    @Cito
    Member

    Thanks for contributing to GraphQL-core and trying to improve performance.

    A quick reminder: GraphQL-core aims to be a 1:1 port of GraphQL.js. Please keep this in mind when proposing performance optimizations. Algorithmic improvements and changes that move the code noticeably away from the original design should go into GraphQL.js first; from there they will flow downstream into GraphQL-core. Maintainability, readability and keeping the code design in sync with upstream are just as important to this project as raw performance. If you need maximum speed, a GraphQL library written in a compiled language may be the better choice. That said, Python-specific optimizations that do not conflict with these goals are always welcome.

    In this case, from a quick glance, the first part of the patch looks better in line with these goals than the second part. But I will review this more closely as soon as I find time.

  4. dexhunter commented on Nov 7, 2026

    @dexhunter
    ContributorAuthor

    The two parts of #305 are independent.

    • The first part is the early return with name.isascii() and name.isidentifier(). All valid names return there.
    • The second part changes only the error path for invalid names. Valid names never reach it.

    So the schema build gain (about 25% on the GitHub schema) comes from the first part alone. The second part only makes invalid names fail faster. It is safe to drop it and keep the original is_name_continue / is_name_start checks and messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions