-
Notifications
You must be signed in to change notification settings - Fork 770
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
update extract_argument
to use Bound APIs
#3708
Conversation
CodSpeed Performance ReportMerging #3708 will improve performances by 13.02%Comparing Summary
Benchmarks breakdown
|
Hmm I'll investigate later why this hasn't yielded the speedup I've seen in #3606, there's likely some other part I need to merge first... |
Ah, I think it's |
18226c6
to
6668785
Compare
3555727
to
5dc78b7
Compare
36189d4
to
1fe867b
Compare
The performance regressions with the Probably the right approach is to get this PR merged (well, needs #3784 reviewed and merged first) and also #3792. Then I think there will be enough pieces in place to deal with updating the proc macro internals in a follow-up. |
befcd39
to
5591f9b
Compare
5591f9b
to
dcd20f4
Compare
1acb54d
to
2f956f4
Compare
2f956f4
to
1301ee1
Compare
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.
Whew, I think this is finally ready to review and I'll deal with the PyRef
/PyCell
changes separately.
type Any<'py> = Bound<'py, PyAny>; | ||
type Dict<'py> = Bound<'py, PyDict>; | ||
type Tuple<'py> = Bound<'py, PyTuple>; |
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.
Clippy was warning about type complexity in the return value tuples without defining these aliases.
@@ -357,7 +357,7 @@ impl<'py> PyStringMethods<'py> for Bound<'py, PyString> { | |||
impl<'a> Borrowed<'a, '_, PyString> { | |||
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))] | |||
#[allow(clippy::wrong_self_convention)] | |||
fn to_str(self) -> PyResult<&'a str> { | |||
pub(crate) fn to_str(self) -> PyResult<&'a str> { |
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.
Used in keyword argument extraction from borrowed keyword names.
src/types/dict.rs
Outdated
impl<'py> Bound<'py, PyDict> { | ||
/// Iterates over the contents of this dictionary without incrementing reference counts. | ||
/// | ||
/// # Safety | ||
/// It must be known that this dictionary will not be modified during iteration. | ||
pub(crate) unsafe fn iter_borrowed<'a>(&'a self) -> BorrowedDictIter<'a, 'py> { | ||
BorrowedDictIter::new(self) | ||
} | ||
} |
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.
The purpose of adding this crate-private API was that I wanted to keep keyword argument processing using Borrowed
for both the "fastcall" and default calling conventions. As far as I am aware, argument processing can safely process a kwargs
dict in this way because it's the only referee of the kwargs dict.
let result = #call; | ||
result |
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.
These changes to return result
on a separate line were caused by the fact that #call
creates a borrow on _args
and _kwargs
, which now have Drop
implementations due to being Bound<PyTuple>
and Option<Bound<PyDict>>
(if *args
, or **kwargs
are accepted).
So to satisfy the borrow checker we had to split the expression like this.
I think given our decision in macro code is to trend away from a single giant expression anyway, and it'll help me in #3847 where I need to do this too, this seemed a reasonable adjustment to me.
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 spotted one nit.
Co-authored-by: Lily Foote <code@lilyf.org>
src/impl_/extract_argument.rs
Outdated
if let Some(kwnames) = py.from_borrowed_ptr_or_opt::<PyTuple>(kwnames) { | ||
|
||
// Safety: kwnames is known to be a pointer to a tuple, or null | ||
let kwnames: &'py Option<Bound<'py, PyTuple>> = std::mem::transmute(&kwnames); |
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.
Maybe we want to create a Bound::ref_from_ptr_or_opt
to avoid std::mem::transmute
?
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.
In the end I adjusted the iter_borrowed()
implementations to allow calling them from a Borrowed
instance, and then I was able to use Borrowed::from_ptr
methods in this code here. I think it's fine to use Borrowed
instead of ref_from_ptr
here because we can control that pesky borrowed lifetime 'a
without worrying about user code, unlike the macros.
Thanks for the reviews! I've removed the |
6490983
to
31616ed
Compare
31616ed
to
89913e8
Compare
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.
Looking good! Just a few nitpicks.
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 spotted a few Borrowed::from_ptr
calls in proc macro generated code. It might be nice to replace them with BoundRef
if possible, for a bit of extra safety. Otherwise LGTM!
Thanks both, I'll aim to tidy this up tomorrow 👍 |
Co-authored-by: Lily Foote <code@lilyf.org>
Thanks both, think we're finally there on this one! |
What is the latest result btw? |
#3708 (comment), but I think it's quite likely that parts of the speedup already got merged now, given how many times this got split up. I will probably analyze again some time and see if there's any further tricks to apply here, but for now I think this is good. |
Builds upon #3681 to move our internal argument extraction mechanisms off the GIL Pool.
Only the last commit is new, and I don't think this is worth reviewing right until #3681 is in, after which I'll rebase and tidy this a bit further. Pushing now purely because I think this should hopefully demonstrate a tantalising performance speedup which we're so close to merging! 😂