You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PERF: Remove use of generators in Cython code #898
I'm not sure. In our specific case, Cython is creating the most general code possible here that could iterate over anything, but we "know" from the type annotations that it's always a list or a tuple (which should be much easier to iterate over). I don't know if the Cython compiler has enough context already to special case for that and make the transformation. I'll poke around and see...
Additionally, if it matters, these could probably benefit from a mapping where the keys are always integers, rather than a general Python dictionary.
Does Cython already support optimizing dict access with known kv-types? I am not aware of this capability, if so it'd be great! Or maybe you have in mind c++ dicts?
Another place where we could enjoy optimization is to rely on the fact that these error-code dicts are read-only after construction, but again I am not aware of Cython being able to optimize for this use case.
Does Cython already support optimizing dict access with known kv-types? I am not aware of this capability, if so it'd be great! Or maybe you have in mind c++ dicts?
No, I don't think it does -- I was suggesting we would pull from somewhere else (probably the C++ stdlib).
Another place where we could enjoy optimization is to rely on the fact that these error-code dicts are read-only after construction, but again I am not aware of Cython being able to optimize for this use case.
Yeah, that's a good point. I /think/ the keys are even compile-time constants, so you could use something like a perfect hash library (though that's probably overkill).
It seems that generator expressions are not performant, but comparing the codegen for a list comprehension versus an append-in-for-loop approach I couldn't see any meaningful difference in the generated code.
It seems that generator expressions are not performant, but comparing the codegen for a list comprehension versus an append-in-for-loop approach I couldn't see any meaningful difference in the generated code.
which is basically changing all to any (which has an early return). Is this the main reason we improve perf, or is Cython just really bad at compiling generator code?
which is basically changing all to any (which has an early return). Is this the main reason we improve perf, or is Cython just really bad at compiling generator code?
We could test the theory by transforming to any(not isinstance..., but I don't think that's the source of the difference.
The main difference is that Python generators are extremely general and operate by making numerous C functions calls, so would be hard for Cython to optimize. Maybe if it has enough context about the type it could transform it into a for loop, but I don't think it currently does that.
Closing since we could not prove in #940 that using a plain for loop actually helps improve the performance, at least not with the benchmark scripts that we crafted there. We'll have to revisit this when there's a more realistic benchmark.
Activity
kkraus14 commentedon Aug 25, 2025
Do you have any sense as to how hard it would be to improve this upstream? We should be able to adopt new Cython versions relatively easily.
mdboom commentedon Aug 25, 2025
I'm not sure. In our specific case, Cython is creating the most general code possible here that could iterate over anything, but we "know" from the type annotations that it's always a list or a tuple (which should be much easier to iterate over). I don't know if the Cython compiler has enough context already to special case for that and make the transformation. I'll poke around and see...
mdboom commentedon Aug 25, 2025
Some specific examples that create generators now:
is better as:
During generated class construction every class has something like:
Since the class is code-generated by cython-gen anyway, this would be much better as:
because it can take advantage of knowing the fixed size of the class etc. (But these changes would only affect import times, not run times).
Additionally, if it matters, these could probably benefit from a mapping where the keys are always integers, rather than a general Python dictionary.
leofang commentedon Aug 25, 2025
Does Cython already support optimizing dict access with known kv-types? I am not aware of this capability, if so it'd be great! Or maybe you have in mind c++ dicts?
Another place where we could enjoy optimization is to rely on the fact that these error-code dicts are read-only after construction, but again I am not aware of Cython being able to optimize for this use case.
mdboom commentedon Aug 26, 2025
No, I don't think it does -- I was suggesting we would pull from somewhere else (probably the C++ stdlib).
Yeah, that's a good point. I /think/ the keys are even compile-time constants, so you could use something like a perfect hash library (though that's probably overkill).
cpcloud commentedon Aug 26, 2025
I'm happy to take this on as a good first issue. @mdboom Are you actively working on this at the moment?
mdboom commentedon Aug 27, 2025
No, go for it!
cpcloud commentedon Aug 29, 2025
It seems that generator expressions are not performant, but comparing the codegen for a list comprehension versus an append-in-for-loop approach I couldn't see any meaningful difference in the generated code.
mdboom commentedon Sep 2, 2025
Cool. Thanks for the confirmation.
leofang commentedon Sep 3, 2025
@mdboom @cpcloud Question: We are changing
to
which is basically changing
alltoany(which has an early return). Is this the main reason we improve perf, or is Cython just really bad at compiling generator code?mdboom commentedon Sep 3, 2025
We could test the theory by transforming to
any(not isinstance..., but I don't think that's the source of the difference.The main difference is that Python generators are extremely general and operate by making numerous C functions calls, so would be hard for Cython to optimize. Maybe if it has enough context about the type it could transform it into a for loop, but I don't think it currently does that.
leofang commentedon Sep 16, 2025
Closing since we could not prove in #940 that using a plain for loop actually helps improve the performance, at least not with the benchmark scripts that we crafted there. We'll have to revisit this when there's a more realistic benchmark.