From 3173162892f5ea40816c177ae575b982bdd9bfbf Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Wed, 6 Apr 2022 17:58:48 +0200 Subject: [PATCH 1/2] Delay formatting type errors to improve performance of failed extractions. --- benches/array.rs | 24 +++++++++++++++++++++- src/error.rs | 53 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/benches/array.rs b/benches/array.rs index 3f6c155bb..eed05afef 100644 --- a/benches/array.rs +++ b/benches/array.rs @@ -6,7 +6,29 @@ use test::{black_box, Bencher}; use std::ops::Range; use numpy::{PyArray1, PyArray2, PyArray3}; -use pyo3::{Python, ToPyObject}; +use pyo3::{PyAny, Python, ToPyObject}; + +#[bench] +fn extract_success(bencher: &mut Bencher) { + Python::with_gil(|py| { + let any: &PyAny = PyArray2::::zeros(py, (10, 10), false); + + bencher.iter(|| { + black_box(any).extract::<&PyArray2>().unwrap(); + }); + }); +} + +#[bench] +fn extract_failure(bencher: &mut Bencher) { + Python::with_gil(|py| { + let any: &PyAny = PyArray2::::zeros(py, (10, 10), false); + + bencher.iter(|| { + black_box(any).extract::<&PyArray2>().unwrap_err(); + }); + }); +} struct Iter(Range); diff --git a/src/error.rs b/src/error.rs index 30e270a39..13586fa84 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,7 +3,7 @@ use std::error::Error; use std::fmt; -use pyo3::{exceptions::PyTypeError, PyErr, PyErrArguments, PyObject, Python, ToPyObject}; +use pyo3::{exceptions::PyTypeError, Py, PyErr, PyErrArguments, PyObject, Python, ToPyObject}; use crate::dtype::PyArrayDescr; @@ -59,32 +59,51 @@ impl_pyerr!(DimensionalityError); /// Represents that types of the given arrays do not match. #[derive(Debug)] -pub struct TypeError { - from: String, - to: String, +pub struct TypeError<'a> { + from: &'a PyArrayDescr, + to: &'a PyArrayDescr, } -impl TypeError { - pub(crate) fn new(from: &PyArrayDescr, to: &PyArrayDescr) -> Self { - let dtype_to_str = |dtype: &PyArrayDescr| { - dtype - .str() - .map_or_else(|_| "(unknown)".into(), |s| s.to_string_lossy().into_owned()) - }; - Self { - from: dtype_to_str(from), - to: dtype_to_str(to), - } +impl<'a> TypeError<'a> { + pub(crate) fn new(from: &'a PyArrayDescr, to: &'a PyArrayDescr) -> Self { + Self { from, to } } } -impl fmt::Display for TypeError { +impl fmt::Display for TypeError<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "type mismatch:\n from={}, to={}", self.from, self.to) } } -impl_pyerr!(TypeError); +impl Error for TypeError<'_> {} + +struct TypeErrorArguments { + from: Py, + to: Py, +} + +impl PyErrArguments for TypeErrorArguments { + fn arguments(self, py: Python) -> PyObject { + let err = TypeError { + from: self.from.as_ref(py), + to: self.to.as_ref(py), + }; + + err.to_string().to_object(py) + } +} + +impl From> for PyErr { + fn from(err: TypeError<'_>) -> PyErr { + let args = TypeErrorArguments { + from: err.from.into(), + to: err.to.into(), + }; + + PyTypeError::new_err(args) + } +} /// Represents that given `Vec` cannot be treated as an array. #[derive(Debug)] From 97201026b463663ff65465f9d3f2acd4a7606afe Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Wed, 6 Apr 2022 22:51:47 +0200 Subject: [PATCH 2/2] Actually remove DimensionalityError and TypeError from the crate API as they are never used directly. --- CHANGELOG.md | 1 + src/lib.rs | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d4769872..478e7acca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - The `inner`, `dot` and `einsum` functions can also return a scalar instead of a zero-dimensional array to match NumPy's types ([#285](https://github.com/PyO3/rust-numpy/pull/285)) - The `PyArray::resize` function supports n-dimensional contiguous arrays. ([#312](https://github.com/PyO3/rust-numpy/pull/312)) - Deprecate `PyArray::from_exact_iter` after optimizing `PyArray::from_iter`. ([#292](https://github.com/PyO3/rust-numpy/pull/292)) + - Remove `DimensionalityError` and `TypeError` from the public API as they never used directly. ([#315](https://github.com/PyO3/rust-numpy/pull/315)) - Fix returning invalid slices from `PyArray::{strides,shape}` for rank zero arrays. ([#303](https://github.com/PyO3/rust-numpy/pull/303)) - v0.16.2 diff --git a/src/lib.rs b/src/lib.rs index 837472feb..ff48e0123 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,9 +61,7 @@ pub use crate::borrow::{ }; pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray}; pub use crate::dtype::{dtype, Complex32, Complex64, Element, PyArrayDescr}; -pub use crate::error::{ - BorrowError, DimensionalityError, FromVecError, NotContiguousError, TypeError, -}; +pub use crate::error::{BorrowError, FromVecError, NotContiguousError}; pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API}; #[allow(deprecated)] pub use crate::npyiter::{