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
davidhewitt
left a comment
There was a problem hiding this comment.
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.
Clippy was warning about type complexity in the return value tuples without defining these aliases.
| #[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.
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.
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.
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.
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.
Maybe we want to create a Bound::ref_from_ptr_or_opt to avoid std::mem::transmute?
There was a problem hiding this comment.
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
LilyFirefly
left a comment
There was a problem hiding this comment.
Looking good! Just a few nitpicks.
Icxolu
left a comment
There was a problem hiding this comment.
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! 😂