You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
_Py_IDENTIFIER declares a static variable, and _PyObject_GetAttrId knows how to translate that back into a PyObject *. This importantly avoids the overhead of allocating a new str object and copying a value into it, each time the function is called.
pyo3 has the same issue, a standard py_any.getattr("attribute") will call <&str as ToPyObject>::to_object which will allocate a new str object. Inefficient!
The goal of this issue is to brainstorm on what can be done to improve this. To start the conversation I did an implementation that reused the CPython implementation:
You can see the only difference between the benchmarks is sys.getattr("version") vs sys.getattr(pyid!(version)). This achieves roughly a 4x speedup:
~/p/h/pyo3-identifier ❯❯❯ cargo +nightly bench
Finished bench [optimized] target(s) in 0.01s
Running unittests src/lib.rs (target/release/deps/pyo3_identifier-0ace08c40c3c7437)
running 2 tests
test tests::bench_normal_getattr ... bench: 60 ns/iter (+/- 0)
test tests::test_bench_id_getattr ... bench: 15 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 0.75s
Unfortunately, this digs deep into the bowels of CPython implementation details -- _Py_Identifier is not part of the public API (much less the stable ABI). The implementation I have here works with CPython 3.9, but not 3.10 (I didn't test older versions).
Hopefully this can be a jumping off point to thinking about whether there's a way pyo3 can offer a similarly better performing API that doesn't rely on a CPython implementation detail.
The text was updated successfully, but these errors were encountered:
This seems to use module state, if I'm reading correctly. A similar approach could work for pyo3, though I don't believe there's currently a Rust API for it.
CPython has an internal API for caching
PyObject *
for string literals, for example:https://github.com/python/cpython/blob/d87f1b787ed38dfd307d82452f2efe9dc5b93942/Modules/_json.c#L326-L327
_Py_IDENTIFIER
declares astatic
variable, and_PyObject_GetAttrId
knows how to translate that back into aPyObject *
. This importantly avoids the overhead of allocating a newstr
object and copying a value into it, each time the function is called.pyo3 has the same issue, a standard
py_any.getattr("attribute")
will call<&str as ToPyObject>::to_object
which will allocate a newstr
object. Inefficient!The goal of this issue is to brainstorm on what can be done to improve this. To start the conversation I did an implementation that reused the CPython implementation:
You can see the only difference between the benchmarks is
sys.getattr("version")
vssys.getattr(pyid!(version))
. This achieves roughly a 4x speedup:Unfortunately, this digs deep into the bowels of CPython implementation details --
_Py_Identifier
is not part of the public API (much less the stable ABI). The implementation I have here works with CPython 3.9, but not 3.10 (I didn't test older versions).Hopefully this can be a jumping off point to thinking about whether there's a way
pyo3
can offer a similarly better performing API that doesn't rely on a CPython implementation detail.The text was updated successfully, but these errors were encountered: