From 40437c56648a046423b266b488cdd86a780a2538 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 4 Jul 2023 21:50:04 +0100 Subject: [PATCH 1/2] add tuple_into_py benchmark --- benches/bench_tuple.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/benches/bench_tuple.rs b/benches/bench_tuple.rs index 07d7fe2dbda..9941b901db7 100644 --- a/benches/bench_tuple.rs +++ b/benches/bench_tuple.rs @@ -83,6 +83,12 @@ fn tuple_to_list(b: &mut Bencher<'_>) { }); } +fn tuple_into_py(b: &mut Bencher<'_>) { + Python::with_gil(|py| { + b.iter(|| -> PyObject { (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).into_py(py) }); + }); +} + fn criterion_benchmark(c: &mut Criterion) { c.bench_function("iter_tuple", iter_tuple); c.bench_function("tuple_new", tuple_new); @@ -92,6 +98,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("sequence_from_tuple", sequence_from_tuple); c.bench_function("tuple_new_list", tuple_new_list); c.bench_function("tuple_to_list", tuple_to_list); + c.bench_function("tuple_into_py", tuple_into_py); } criterion_group!(benches, criterion_benchmark); From 867a12bb5a57beacc8218ba0e9a75b83bbf38319 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 4 Jul 2023 23:02:39 +0100 Subject: [PATCH 2/2] use `PyTuple_Pack` in fixed-size tuple conversions --- src/types/tuple.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 14c32a27f2b..e06210af11a 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -284,22 +284,24 @@ fn wrong_tuple_length(t: &PyTuple, expected_length: usize) -> PyErr { macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => { impl <$($T: ToPyObject),+> ToPyObject for ($($T,)+) { fn to_object(&self, py: Python<'_>) -> PyObject { - unsafe { - let ptr = ffi::PyTuple_New($length); - let ret = PyObject::from_owned_ptr(py, ptr); - $(ffi::PyTuple_SetItem(ptr, $n, self.$n.to_object(py).into_ptr());)+ - ret + #[inline] + fn inner(py: Python<'_>, $($refN: PyObject),+) -> PyObject { + unsafe { + PyObject::from_owned_ptr(py, ffi::PyTuple_Pack($length, $($refN.as_ptr()),+)) + } } + inner(py, $(self.$n.to_object(py)),+) } } impl <$($T: IntoPy),+> IntoPy for ($($T,)+) { fn into_py(self, py: Python<'_>) -> PyObject { - unsafe { - let ptr = ffi::PyTuple_New($length); - let ret = PyObject::from_owned_ptr(py, ptr); - $(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_py(py).into_ptr());)+ - ret + #[inline] + fn inner(py: Python<'_>, $($refN: PyObject),+) -> PyObject { + unsafe { + Py::from_owned_ptr(py, ffi::PyTuple_Pack($length, $($refN.as_ptr()),+)) + } } + inner(py, $(self.$n.into_py(py)),+) } #[cfg(feature = "experimental-inspect")] @@ -310,12 +312,13 @@ fn type_output() -> TypeInfo { impl <$($T: IntoPy),+> IntoPy> for ($($T,)+) { fn into_py(self, py: Python<'_>) -> Py { - unsafe { - let ptr = ffi::PyTuple_New($length); - let ret = Py::from_owned_ptr(py, ptr); - $(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_py(py).into_ptr());)+ - ret + #[inline] + fn inner(py: Python<'_>, $($refN: PyObject),+) -> Py { + unsafe { + Py::from_owned_ptr(py, ffi::PyTuple_Pack($length, $($refN.as_ptr()),+)) + } } + inner(py, $(self.$n.into_py(py)),+) } #[cfg(feature = "experimental-inspect")]