Question about specialization logic for object types in Cython codebase/Cython compiler optimisations

24 views
Skip to first unread message

аbebus

unread,
Oct 14, 2025, 10:46:33 AMOct 14
to cython...@googlegroups.com

Hi everyone,


I’m trying to understand how Cython decides when to emit specialized C-API calls, and where that logic is implemented in the codebase.


To clarify what I am asking about: I am specifically interested in specialization for general Python object types, not numeric optimizations. I’m already aware that Cython can cast int objects to raw C integers where possible, that is not my focus here.


Instead, I’m looking at protocol-based types such as sequences or mappings. For example:

- If the static type of a variable is known to be a Sequence, then calling len(obj) could in theory be compiled to PySequence_Length(obj).

- However, Cython currently appears to emit PyObject_Length(obj) instead, without using that type information.


So my questions are:

1. Where in the Cython codebase does it decide which C-API call to use for operations like len()?

2. Under what conditions does Cython currently specialize operations for object protocol types (e.g. Sequence, Mapping)? Is this handled anywhere, or would it require new machinery?

3. Aside from the familiar for i in range(...) loop optimization, what non-numeric patterns does Cython currently recognize and optimize?


Any pointers, even just a relevant module or filename, would be very helpful


Thanks a lot in advance!

da-woods

unread,
Oct 14, 2025, 1:37:50 PMOct 14
to cython...@googlegroups.com

Hi,

Mostly Cython emits code for specific object types (e.g. list/tuple/dict).

The main issue is: what do you mean when you say "the static type of a variable is known to be a Sequence"? We don't currently anything with `collections.abc.Sequence` as a type-hint, mainly because it isn't that useful. It defines a Python protocol (that `__getitem__` exists and will take a Python integer) rather than saying that it's implemented in terms of `PySequenceMethods`.

People do occasionally ask for a way to prefer `PySequence_GetItem` because that is quicker for C sequences that `PyObject_GetItem`. The issue is mainly that we don't have a good way of indicating the type. And you can always just use `PySequence_GetItem` from the C API.

Most of the code you're looking for is in Cython/Compiler/Optimize.py. As I say - it's specialized for specific exact types rather than "protocol types".

I don't think it's realistic to make a list of optimizations that Cython performs (there's lots of them in lots of places) - there's definitely lots of loop optimizations for different known types though.

David

--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/cython-users/CAL%2BXva7KT-F%3D7gN0ZydwuNcCCQX1XBgvUt7u4aMtH%2By8Wz3hTg%40mail.gmail.com.

аbebus

unread,
Oct 18, 2025, 12:05:37 PMOct 18
to cython-users
Thanks for the explanation!

Yes, I was thinking about the idea of automagically emitting something like `PySequence_Fast_GET_SIZE` when there’s already an isinstance check for that object. But you’re right, I can just call the C API manually when I know it’s safe.

One more question: do you think Cython might ever attempt specialisation similar to what the Python 3.11+ interpreter does? I realise Cython can’t observe runtime behaviour like the interpreter does, but could it happen based on trusted isinstance checks or type annotations provided by the user?

вторник, 14 октября 2025 г. в 20:37:50 UTC+3, D Woods:

Stefan Behnel

unread,
Oct 18, 2025, 12:16:42 PMOct 18
to cython...@googlegroups.com
Hi,

аbebus schrieb am 18.10.25 um 17:56:
> I was thinking about the idea of automagically emitting something like
> `PySequence_Fast_GET_SIZE`

You should make sure that this helps the performance. The function is
called "…Fast…", but that doesn't mean that it _is_ fast. It might be quite
slow for your use case. We avoid CPython's "PySequence_Fast_*()" API
internally in Cython because it is too slow for the code that we want to
generate.

Manually special casing the Python 'list' type can easily be much faster
(and Cython does that internally for for-loops, for example).

As always with code optimisation, guesses are likely wrong. Don't guess,
measure.


> One more question: do you think Cython might ever attempt specialisation
> similar to what the Python 3.11+ interpreter does? I realise Cython can’t
> observe runtime behaviour like the interpreter does, but could it happen
> based on trusted isinstance checks or type annotations provided by the user?
The way to do it in Cython is to apply static type declarations. Cython
does some optimistic optimisation internally, but it's so easy to beat any
optimistic branches with explicit static typing that users should always
prefer that.

You might want to look into Cython's fused types if you intend to generate
special cased code for different data types and collections.

Stefan

аbebus

unread,
Oct 18, 2025, 12:38:27 PMOct 18
to cython-users

Thanks a lot for the detailed explanation, that’s very helpful.

I’ll definitely benchmark instead of assuming based on naming :) An also I’ll take a closer look at fused types as you suggested: that might be exactly what I need.

Thanks again for taking the time to clarify all this!

Best,

Albert



суббота, 18 октября 2025 г. в 19:16:42 UTC+3, Stefan Behnel:
Reply all
Reply to author
Forward
0 new messages