Skip to content

Commit 2f624af

Browse files
committed
Merge branch 'master' into smart_holder
2 parents 4880140 + ad6bf5c commit 2f624af

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

include/pybind11/cast.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,11 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
13751375
template <typename Derived>
13761376
template <return_value_policy policy, typename... Args>
13771377
object object_api<Derived>::operator()(Args &&...args) const {
1378+
#if !defined(NDEBUG) && PY_VERSION_HEX >= 0x03060000
1379+
if (!PyGILState_Check()) {
1380+
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
1381+
}
1382+
#endif
13781383
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr());
13791384
}
13801385

tests/test_callbacks.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,10 @@ TEST_SUBMODULE(callbacks, m) {
172172
for (auto i : work)
173173
start_f(py::cast<int>(i));
174174
});
175+
176+
m.def("callback_num_times", [](py::function f, std::size_t num) {
177+
for (std::size_t i = 0; i < num; i++) {
178+
f();
179+
}
180+
});
175181
}

tests/test_callbacks.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import pytest
33
from pybind11_tests import callbacks as m
44
from threading import Thread
5+
import time
56

67

78
def test_callbacks():
@@ -146,3 +147,34 @@ def test_async_async_callbacks():
146147
t = Thread(target=test_async_callbacks)
147148
t.start()
148149
t.join()
150+
151+
152+
def test_callback_num_times():
153+
# Super-simple micro-benchmarking related to PR #2919.
154+
# Example runtimes (Intel Xeon 2.2GHz, fully optimized):
155+
# num_millions 1, repeats 2: 0.1 secs
156+
# num_millions 20, repeats 10: 11.5 secs
157+
one_million = 1000000
158+
num_millions = 1 # Try 20 for actual micro-benchmarking.
159+
repeats = 2 # Try 10.
160+
rates = []
161+
for rep in range(repeats):
162+
t0 = time.time()
163+
m.callback_num_times(lambda: None, num_millions * one_million)
164+
td = time.time() - t0
165+
rate = num_millions / td if td else 0
166+
rates.append(rate)
167+
if not rep:
168+
print()
169+
print(
170+
"callback_num_times: {:d} million / {:.3f} seconds = {:.3f} million / second".format(
171+
num_millions, td, rate
172+
)
173+
)
174+
if len(rates) > 1:
175+
print("Min Mean Max")
176+
print(
177+
"{:6.3f} {:6.3f} {:6.3f}".format(
178+
min(rates), sum(rates) / len(rates), max(rates)
179+
)
180+
)

0 commit comments

Comments
 (0)