From f1435c7e6b068a1ed13ebd3db597ea3bb15aa398 Mon Sep 17 00:00:00 2001 From: Sergei Lebedev Date: Wed, 28 Aug 2019 17:52:41 +0100 Subject: [PATCH] Extract exception name via tp_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is faster than dynamically looking up __name__ via GetAttrString. Note though that the runtime of the code throwing an error_already_set will be dominated by stack unwinding so the improvement will not be noticeable. Before: 396 ns ± 0.913 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) After: 277 ns ± 0.549 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) Benchmark: const std::string foo() { PyErr_SetString(PyExc_KeyError, ""); const std::string &s = py::detail::error_string(); PyErr_Clear(); return s; } PYBIND11_MODULE(foo, m) { m.def("foo", &::foo); } --- include/pybind11/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 8bcf81761..c02708195 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -413,7 +413,7 @@ PYBIND11_NOINLINE inline std::string error_string(PyObject* type, PyObject* valu // normalized by the caller? std::string errorString; if (type) { - errorString += handle(type).attr("__name__").cast(); + errorString += static_cast(reinterpret_cast(type)->tp_name); errorString += ": "; } if (value)