mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +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 <typename Derived>
|
||||||
template <return_value_policy policy, typename... Args>
|
template <return_value_policy policy, typename... Args>
|
||||||
object object_api<Derived>::operator()(Args &&...args) const {
|
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());
|
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,4 +172,10 @@ TEST_SUBMODULE(callbacks, m) {
|
|||||||
for (auto i : work)
|
for (auto i : work)
|
||||||
start_f(py::cast<int>(i));
|
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
|
import pytest
|
||||||
from pybind11_tests import callbacks as m
|
from pybind11_tests import callbacks as m
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
def test_callbacks():
|
def test_callbacks():
|
||||||
@ -146,3 +147,34 @@ def test_async_async_callbacks():
|
|||||||
t = Thread(target=test_async_callbacks)
|
t = Thread(target=test_async_callbacks)
|
||||||
t.start()
|
t.start()
|
||||||
t.join()
|
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