-
Notifications
You must be signed in to change notification settings - Fork 776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reintroduce vectorcall
optimization with new PyCallArgs
trait
#4768
base: main
Are you sure you want to change the base?
Conversation
Copilot
AI
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 suggestion.
Comments skipped due to low confidence (1)
src/call.rs:1
- The TODO comment should be replaced with meaningful documentation.
//! TODO
CodSpeed Performance ReportMerging #4768 will improve performances by 58.61%Comparing 🎉 Hooray!
|
Benchmark | main |
Icxolu:pycallargs |
Change | |
---|---|---|---|---|
⚡ | call |
756.5 µs | 620.5 µs | +21.92% |
⚡ | call_1 |
380.3 µs | 271 µs | +40.32% |
⚡ | call_method |
1.4 ms | 1.3 ms | +10.73% |
⚡ | call_method_1 |
1,017.5 µs | 641.5 µs | +58.61% |
⚡ | call_method_one_arg |
965.9 µs | 611.7 µs | +57.91% |
⚡ | call_one_arg |
347.9 µs | 242.1 µs | +43.66% |
Looks like it worked! If we're roughly happy with this, I'll work on the docs. |
It looks like we can even enable some of it on the limited api after 3.12: https://docs.python.org/3/c-api/call.html#c.PyObject_Vectorcall, but I don't think we have the ffi definitions yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Always so satisfying to see such big perf wins. 😂
I actually have the FFI bindings in #4379 but I haven't completed splitting that PR up.
|
||
/// TODO | ||
pub trait PyCallArgs<'py>: Sized + private::Sealed { | ||
#[doc(hidden)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a good idea to have all the methods hidden and the type sealed; we can explain the situation with docs 👍.
Especially if in the long term we might have something like #4414 to solve keyword args (although much design experimentation still needed to make sure we're all happy with whatever we come up with).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a first pass on the docs, let we know what you think.
This reintroduces the
vectorcall
optimization we removed temporarily in #4653 using a newPyCallArgs
trait as was discussed during the initial implementation in #4456.This slightly reduces the number of types that can be passed to
PyAnyMethods::call
and friends. With this only Rust tuples (including unit),Bound<PyTuple>
andPy<PyTuple>
are allowed (instead of any type that can be converted into aPyTuple
viaIntoPyObject
as before). Insidepyo3
there is no such type, but there could be user types (for example#[derive(IntoPyObject)]
tuple structs) that won't work anymore. The work around is to simply convert at the call site, so I don't think that's a huge blocker.There are still possibilities left open with regards to
kwargs
. One idea could be aPyCallArgs
type with a builder like API to set both, positional and keyword args which can than be transformed as needed depending on the calling convention (maybe with something likesmallvec
or evenheapless::Vec
to avoid lots of small allocation). I might explore that as a followup.Closes #4656