mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Adding PyGILState_Check() in object_api<>::operator(). (#2919)
* Adding PyGILState_Check() in object_api<>::operator(). * Enabling PyGILState_Check() for Python >= 3.6 only. Possibly, this explains why PyGILState_Check() cannot safely be used with Python 3.4 and 3.5: https://github.com/python/cpython/pull/10267#issuecomment-434881587 * Adding simple micro benchmark. * Reducing test time to minimum (purely for coverage, not for accurate results). * Fixing silly oversight. * Minor code organization improvement in test. * Adding example runtimes. * Removing capsys (just run with `-k test_callback_num_times -s` and using `.format()`.
This commit is contained in:
parent
f676782bec
commit
ad6bf5cd39
@ -1348,6 +1348,11 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
|
||||
template <typename Derived>
|
||||
template <return_value_policy policy, typename... Args>
|
||||
object object_api<Derived>::operator()(Args &&...args) const {
|
||||
#if !defined(NDEBUG) && PY_VERSION_HEX >= 0x03060000
|
||||
if (!PyGILState_Check()) {
|
||||
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
|
||||
}
|
||||
#endif
|
||||
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr());
|
||||
}
|
||||
|
||||
|
@ -172,4 +172,10 @@ TEST_SUBMODULE(callbacks, m) {
|
||||
for (auto i : work)
|
||||
start_f(py::cast<int>(i));
|
||||
});
|
||||
|
||||
m.def("callback_num_times", [](py::function f, std::size_t num) {
|
||||
for (std::size_t i = 0; i < num; i++) {
|
||||
f();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
import pytest
|
||||
from pybind11_tests import callbacks as m
|
||||
from threading import Thread
|
||||
import time
|
||||
|
||||
|
||||
def test_callbacks():
|
||||
@ -146,3 +147,34 @@ def test_async_async_callbacks():
|
||||
t = Thread(target=test_async_callbacks)
|
||||
t.start()
|
||||
t.join()
|
||||
|
||||
|
||||
def test_callback_num_times():
|
||||
# Super-simple micro-benchmarking related to PR #2919.
|
||||
# Example runtimes (Intel Xeon 2.2GHz, fully optimized):
|
||||
# num_millions 1, repeats 2: 0.1 secs
|
||||
# num_millions 20, repeats 10: 11.5 secs
|
||||
one_million = 1000000
|
||||
num_millions = 1 # Try 20 for actual micro-benchmarking.
|
||||
repeats = 2 # Try 10.
|
||||
rates = []
|
||||
for rep in range(repeats):
|
||||
t0 = time.time()
|
||||
m.callback_num_times(lambda: None, num_millions * one_million)
|
||||
td = time.time() - t0
|
||||
rate = num_millions / td if td else 0
|
||||
rates.append(rate)
|
||||
if not rep:
|
||||
print()
|
||||
print(
|
||||
"callback_num_times: {:d} million / {:.3f} seconds = {:.3f} million / second".format(
|
||||
num_millions, td, rate
|
||||
)
|
||||
)
|
||||
if len(rates) > 1:
|
||||
print("Min Mean Max")
|
||||
print(
|
||||
"{:6.3f} {:6.3f} {:6.3f}".format(
|
||||
min(rates), sum(rates) / len(rates), max(rates)
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user