Extract exception name via tp_name

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);
}
This commit is contained in:
Sergei Lebedev 2019-08-28 17:52:41 +01:00
parent e289e0ea24
commit f1435c7e6b

View File

@ -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<std::string>();
errorString += static_cast<const std::string>(reinterpret_cast<PyTypeObject*>(type)->tp_name);
errorString += ": ";
}
if (value)