Repository navigation
Performance improvements for the MATCH_CLASS opcode #138912
Copy link
Copy link
Open
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)performancePerformance or resource usagePerformance or resource usagetype-featureA feature request or enhancementA feature request or enhancement
Description
Activity
- addedtype-featureA feature request or enhancementA feature request or enhancement
on Sep 15, 2025 - changed the title
[-]Performance improvements for the MatchClass opcode[/-][+]Performance improvements for the MATCH_CLASS opcode[/+]on Sep 15, 2025 - addedperformancePerformance or resource usagePerformance or resource usageinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Sep 15, 2025 The check for duplicate attribute names is most helpful for mixed positional and keyword class patterns. [...] However, given the more than noticeable performance impact, I'd argue it could be skipped if there are only keywords given.
Seems I missed that the keyword attributes are already validated at compile time. It's a SyntaxError if an attribute name is repeated. So it's safe to skip the additional runtime check if there are only keyword attributes.
Lines 5870 to 5888 in 4e00e25
static int validate_kwd_attrs(compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* patterns) { // Any errors will point to the pattern rather than the arg name as the // parser is only supplying identifiers rather than Name or keyword nodes Py_ssize_t nattrs = asdl_seq_LEN(attrs); for (Py_ssize_t i = 0; i < nattrs; i++) { identifier attr = ((identifier)asdl_seq_GET(attrs, i)); for (Py_ssize_t j = i + 1; j < nattrs; j++) { identifier other = ((identifier)asdl_seq_GET(attrs, j)); if (!PyUnicode_Compare(attr, other)) { location loc = LOC((pattern_ty) asdl_seq_GET(patterns, j)); return _PyCompile_Error(c, loc, "attribute name repeated " "in class pattern: %U", attr); } } } return SUCCESS; } Pinging @markshannon as code owner of Python/ceval.c to review the open PR (other devs welcome to review as well). If no response, I will make a request to DPO in 2 weeks.
- added a commit that references this issue
on Sep 26, 2026 - added 4 commits that reference this issue
on Sep 27, 2026
Metadata
Metadata
Assignees
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)performancePerformance or resource usagePerformance or resource usagetype-featureA feature request or enhancementA feature request or enhancement
Feature or enhancement
Proposal:
For pylint we recently dropped support for Python 3.9 so I'm currently evaluating if we could replace some if statements with match. As most of the checks are similar to AST matching, the class pattern makes a lot of sense. I've noticed though that these are noticeable slower than the corresponding if statements. Yes, technically match does a few more checks which are just omitted in the if clauses but after looking at
_PyEval_MatchClassI believe there is room for additional improvements.Bare class pattern
First let's compare a simple
isinstancecall with the equivalent class pattern (without any attributes).Full micro benchmark
At least on my machine the match statement is 2x slower. This could be avoided if we return early in case there are no arguments, thus skipping the creation of a list to track the attributes and set for the attribute names.
cpython/Python/ceval.c
Lines 743 to 752 in 2d72493
One attribute
One of the most expensive parts of
MatchClassis the set to check for duplicate attribute names. If there is only one attribute, this could be skipped entirely. An additional perf improvement can be archived if the attributes are placed into a tuple directly instead of creating an intermediary list and converting it to a tuple before returning it. That works since the match would fail if the argument count doesn't match.Full micro benchmark
Only keyword arguments
The check for duplicate attribute names is most helpful for mixed positional and keyword class patterns. Users would need to lookup
__match_args__and make sure an attribute isn't accidentally specified twice. However, given the more than noticeable performance impact, I'd argue it could be skipped if there are only keywords given. The worst that would happen is that the match-case would always fail due to conflicting subpatterns. In that case however it would be fairly easy to debug as all keywords are specified directly. Furthermore linters will be able to detect these based on the AST alone.Full micro benchmark
--
I'll be working on a PR for these.
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs