Skip to content

Speed up sequence subscripting using Py_TPFLAGS_SEQUENCE#7432

Merged
scoder merged 37 commits intocython:masterfrom
scoder:seq_getitem
Jan 22, 2026
Merged

Speed up sequence subscripting using Py_TPFLAGS_SEQUENCE#7432
scoder merged 37 commits intocython:masterfrom
scoder:seq_getitem

Conversation

@scoder
Copy link
Copy Markdown
Contributor

@scoder scoder commented Dec 26, 2025

Python semantics dictate that we first try the mapping protocol and then the sequence protocol for subscripting. When the index is a C integer, we can optimise perfectly for list/tuple, but all other sequences suffer from having to build a Python int object for the index to pass it through the mapping lookup if they implement that (e.g. to support extended slicing, like NumPy arrays).

Python 3.10 added type markers (for pattern matching) for explicitly declaring a type as sequence or mapping, called Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING, which can now be checked for quite quickly. If a type is marked as sequence but still implements mapping lookups for slicing, and it supports sequence subscripting, we can avoid the Python int creation of the mapping protocol and go straight through the sequence index lookup.

With this change, indexing into Python's array.array and memoryview types is ~60% faster in a micro-benchmark.
Using a C integer as dict key got slightly slower but is resolved by adding a separate up-front special case.

Benchmark is based on #7431

See
https://docs.python.org/3/c-api/typeobj.html#c.Py_TPFLAGS_SEQUENCE
#1807
pandas-dev/pandas#55915
pandas-dev/pandas#55179 (comment)

@scoder scoder added this to the 3.3 milestone Dec 26, 2025
@da-woods
Copy link
Copy Markdown
Contributor

I think this is reasonable although it's arguably a slight abuse of the flag (which is really only documented as being for pattern matching).

I think a type type that gives a different answer if you go through tp_sequence and tp_mapping is pretty broken. So from that point of view it seems fine to treat this flag as a strong hint and if anyone actually notices a difference in behaviour it's most likely on them.

@scoder
Copy link
Copy Markdown
Contributor Author

scoder commented Jan 22, 2026

NumPy will set the sequence flag in the future: numpy/numpy#30519
Given the expected speedups, I'll merge this as soon as CI is happy.

@scoder scoder enabled auto-merge (squash) January 22, 2026 09:08
@scoder scoder merged commit e39d094 into cython:master Jan 22, 2026
89 checks passed
@scoder scoder deleted the seq_getitem branch January 29, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants