Repository navigation
[libcxx] Avoid a busy-loop in atomic's lost_wakeup.pass.cpp - #211242
Conversation
Using __libcpp_thread_poll_with_backoff brings two improvements. First, in case of a lost wake-up, we get an assertion failure instead of a hang. And second, on single-core or heavily loaded systems, the notifier yield instead of burning all its allocated time on the busy-loop. The measurements were done on my Linux box, the time is the one reported by lit. To isolate the test on a single core I used the following commands: export LIT_FILTER="wait/lost_wakeup.pass.cpp" taskset -c 0 ninja -C build check-cxx | Configuration | Linux futex | | Fallback | | | -------------- | ----------- | ----------- | -------- | ----------- | | | Normal | Pinned core | Normal | Pinned core | | Before | 1.20s | 15.54s | 1.26s | 601.25s | | With backoff | 1.11s | 14.42s | 1.15s | 17.60s |
|
@llvm/pr-subscribers-libcxx Author: Lucas Chollet (LucasChollet) ChangesUsing __libcpp_thread_poll_with_backoff brings two improvements. First, in case of a lost wake-up, we get an assertion failure instead of a hang. And second, on single-core or heavily loaded systems, the notifier yield instead of burning all its allocated time on the busy-loop. The measurements were done on my Linux box, the time is the one reported by lit. To isolate the test on a single core I used the following commands: export LIT_FILTER="wait/lost_wakeup.pass.cpp"
Full diff: https://github.com/llvm/llvm-project/pull/211242.diff 1 Files Affected:
diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/lost_wakeup.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/lost_wakeup.pass.cpp
index 17ad72dd74866..6b486173a4743 100644
--- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/lost_wakeup.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/lost_wakeup.pass.cpp
@@ -14,6 +14,8 @@
// <atomic>
#include <atomic>
+#include <cassert>
+#include <chrono>
#include <functional>
#include <thread>
#include <vector>
@@ -38,8 +40,10 @@ int main(int, char**) {
auto notify = [&] {
for (int i = 0; i < num_iterations; ++i) {
- while (waiter_ready.load() < num_waiters) {
- }
+ assert(std::__libcpp_thread_poll_with_backoff(
+ [&]() -> bool { return waiter_ready.load() == num_waiters; },
+ std::__libcpp_timed_backoff_policy(),
+ std::chrono::seconds(1)) == std::__poll_with_backoff_results::__poll_success);
waiter_ready.store(0);
state.fetch_add(1);
state.notify_all();
|
|
After discussion offline, I think my opinion is that we should avoid using
I wonder if we could just use |
|
Updated this PR to follow your suggestion. I also measured the execution time again and updated the table. |
| auto notify = [&] { | ||
| for (int i = 0; i < num_iterations; ++i) { | ||
| while (waiter_ready.load() < num_waiters) { | ||
| #if !defined(__APPLE__) |
There was a problem hiding this comment.
From #161086 (comment):
I remember that macOS would put the yield thread on the lowest priority on the scheduler. If the machine was overloaded with other running jobs, our notifier thread would have taken long time to resume again.
|
@philnik777 @huixie90 This is ready for review. |
philnik777
left a comment
There was a problem hiding this comment.
I'd really like @huixie90 to take a look at this, since I'm not particularly familiar with this part of the code base.
huixie90
left a comment
There was a problem hiding this comment.
Given the comment here suggested that this change does improve testing time on some platforms #211261 (comment). LGTM
|
Thanks for the approval! I don't have merge permissions though, could you please press the merge button for me? |
Fixes #207763
On single-core or heavily loaded systems, using this_thread::yield()
prevents the notifier from burning all its allocated time on the
busy-loop.
The measurements were done on my Linux box, the time is the one reported
by lit. To isolate the test on a single core I used the following
commands:
export LIT_FILTER="wait/lost_wakeup.pass.cpp"
taskset -c 0 ninja -C build check-cxx
Both configurations are with the
run < 10change.