From 7ddc3099f646af6d0f57a5bdb7251853638ee4ee Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Thu, 14 Jul 2022 16:15:17 +0400 Subject: [PATCH] remove td::this_thread::yield function. usleep_for(1) used instead --- benchmark/bench_queue.cpp | 2 +- td/telegram/net/NetQueryDispatcher.cpp | 2 +- tdutils/td/utils/AtomicRead.h | 12 ++++++++- tdutils/td/utils/MpmcQueue.h | 5 ++-- tdutils/td/utils/MpmcWaiter.h | 16 ++++++++---- tdutils/td/utils/SpinLock.h | 3 ++- .../td/utils/port/detail/ThreadPthread.cpp | 3 --- tdutils/td/utils/port/detail/ThreadPthread.h | 1 - tdutils/td/utils/port/detail/ThreadStl.h | 4 ++- tdutils/td/utils/queue.h | 4 +-- tdutils/td/utils/tests.h | 26 +++++++++++++++++-- 11 files changed, 58 insertions(+), 20 deletions(-) diff --git a/benchmark/bench_queue.cpp b/benchmark/bench_queue.cpp index 0d4911729..6f7cf20bc 100644 --- a/benchmark/bench_queue.cpp +++ b/benchmark/bench_queue.cpp @@ -51,7 +51,7 @@ class Backoff { if (cnt < 50) { return true; } else { - td::this_thread::yield(); + td::usleep_for(1); return cnt < 500; } } diff --git a/td/telegram/net/NetQueryDispatcher.cpp b/td/telegram/net/NetQueryDispatcher.cpp index ccbe5a642..e477379b5 100644 --- a/td/telegram/net/NetQueryDispatcher.cpp +++ b/td/telegram/net/NetQueryDispatcher.cpp @@ -194,7 +194,7 @@ Status NetQueryDispatcher::wait_dc_init(DcId dc_id, bool force) { return Status::Error("Closing"); } #if !TD_THREAD_UNSUPPORTED - td::this_thread::yield(); + td::usleep_for(1); #endif } } diff --git a/tdutils/td/utils/AtomicRead.h b/tdutils/td/utils/AtomicRead.h index a51a91549..58d96e436 100644 --- a/tdutils/td/utils/AtomicRead.h +++ b/tdutils/td/utils/AtomicRead.h @@ -7,6 +7,7 @@ #pragma once #include "td/utils/common.h" +#include "td/utils/port/sleep.h" #include "td/utils/port/thread.h" #include "td/utils/type_traits.h" @@ -20,6 +21,15 @@ template class AtomicRead { public: void read(T &dest) const { + int it = 0; + const int wait_each_it = 4; + auto wait = [&]() { + it++; + if (it % wait_each_it == 0) { + usleep_for(1); + } + }; + while (true) { static_assert(TD_IS_TRIVIALLY_COPYABLE(T), "T must be trivially copyable"); auto version_before = version.load(); @@ -30,7 +40,7 @@ class AtomicRead { break; } } - td::this_thread::yield(); + wait(); } } diff --git a/tdutils/td/utils/MpmcQueue.h b/tdutils/td/utils/MpmcQueue.h index 526bc00be..9d5708586 100644 --- a/tdutils/td/utils/MpmcQueue.h +++ b/tdutils/td/utils/MpmcQueue.h @@ -14,6 +14,7 @@ #include "td/utils/format.h" #include "td/utils/HazardPointers.h" #include "td/utils/logging.h" +#include "td/utils/port/sleep.h" #include "td/utils/port/thread.h" #include "td/utils/ScopeGuard.h" @@ -305,7 +306,7 @@ class MpmcQueueOld { if (try_pop(value, thread_id)) { return value; } - td::this_thread::yield(); + td::usleep_for(1); } } @@ -429,7 +430,7 @@ class MpmcQueue { if (try_pop(value, thread_id)) { return value; } - td::this_thread::yield(); + td::usleep_for(1); } } diff --git a/tdutils/td/utils/MpmcWaiter.h b/tdutils/td/utils/MpmcWaiter.h index b6e0bee0c..7075c3f7c 100644 --- a/tdutils/td/utils/MpmcWaiter.h +++ b/tdutils/td/utils/MpmcWaiter.h @@ -8,6 +8,7 @@ #include "td/utils/common.h" #include "td/utils/logging.h" +#include "td/utils/port/sleep.h" #include "td/utils/port/thread.h" #include @@ -29,16 +30,17 @@ class MpmcEagerWaiter { slot.yields = 0; slot.worker_id = worker_id; } + void wait(Slot &slot) { if (slot.yields < RoundsTillSleepy) { - td::this_thread::yield(); + yield(); slot.yields++; } else if (slot.yields == RoundsTillSleepy) { auto state = state_.load(std::memory_order_relaxed); if (!State::has_worker(state)) { auto new_state = State::with_worker(state, slot.worker_id); if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) { - td::this_thread::yield(); + yield(); slot.yields++; return; } @@ -47,12 +49,12 @@ class MpmcEagerWaiter { return; } } - td::this_thread::yield(); + yield(); slot.yields = 0; } else if (slot.yields < RoundsTillAsleep) { auto state = state_.load(std::memory_order_acquire); if (State::still_sleepy(state, slot.worker_id)) { - td::this_thread::yield(); + yield(); slot.yields++; return; } @@ -121,6 +123,10 @@ class MpmcEagerWaiter { condition_variable_.notify_all(); } } + static void yield() { + // whatever, this is better than sched_yield + usleep_for(1); + } }; class MpmcSleepyWaiter { @@ -208,7 +214,7 @@ class MpmcSleepyWaiter { } if (slot.state_ == Slot::Search) { if (slot.yield_cnt++ < 10 && false) { - td::this_thread::yield(); + // TODO some sleep backoff is possible return; } diff --git a/tdutils/td/utils/SpinLock.h b/tdutils/td/utils/SpinLock.h index 33230b8db..abaee7dff 100644 --- a/tdutils/td/utils/SpinLock.h +++ b/tdutils/td/utils/SpinLock.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/utils/port/sleep.h" #include "td/utils/port/thread.h" #include @@ -30,7 +31,7 @@ class SpinLock { //TODO pause return true; } else { - td::this_thread::yield(); + usleep_for(1); return true; } } diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index a342c3ad1..30234d0aa 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -88,9 +88,6 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at } namespace this_thread_pthread { -void yield() { - sched_yield(); -} ThreadPthread::id get_id() { return pthread_self(); } diff --git a/tdutils/td/utils/port/detail/ThreadPthread.h b/tdutils/td/utils/port/detail/ThreadPthread.h index 5342c76c0..c50546c14 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.h +++ b/tdutils/td/utils/port/detail/ThreadPthread.h @@ -83,7 +83,6 @@ class ThreadPthread { }; namespace this_thread_pthread { -void yield(); ThreadPthread::id get_id(); } // namespace this_thread_pthread } // namespace detail diff --git a/tdutils/td/utils/port/detail/ThreadStl.h b/tdutils/td/utils/port/detail/ThreadStl.h index 5c1a61205..0d9f8f2ff 100644 --- a/tdutils/td/utils/port/detail/ThreadStl.h +++ b/tdutils/td/utils/port/detail/ThreadStl.h @@ -70,7 +70,9 @@ class ThreadStl { return std::forward(v); } }; -namespace this_thread_stl = std::this_thread; +namespace this_thread_stl { +using std::this_thread::get_id; +} // namespace this_thread_stl } // namespace detail } // namespace td diff --git a/tdutils/td/utils/queue.h b/tdutils/td/utils/queue.h index 6157cc808..6e5b67023 100644 --- a/tdutils/td/utils/queue.h +++ b/tdutils/td/utils/queue.h @@ -32,7 +32,7 @@ class Backoff { if (cnt < 1) { // 50 return true; } else { - td::this_thread::yield(); + td::usleep_for(1); return cnt < 3; // 500 } } @@ -47,7 +47,7 @@ class InfBackoff { if (cnt < 50) { return true; } else { - td::this_thread::yield(); + td::usleep_for(1); return true; } } diff --git a/tdutils/td/utils/tests.h b/tdutils/td/utils/tests.h index 183cfe640..2d1b92877 100644 --- a/tdutils/td/utils/tests.h +++ b/tdutils/td/utils/tests.h @@ -10,12 +10,14 @@ #include "td/utils/Context.h" #include "td/utils/format.h" #include "td/utils/logging.h" +#include "td/utils/port/sleep.h" #include "td/utils/port/thread.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" #include #include +#include #include namespace td { @@ -126,12 +128,12 @@ class RegisterTest { } }; -class Stage { +class StageWait { public: void wait(uint64 need) { value_.fetch_add(1, std::memory_order_release); while (value_.load(std::memory_order_acquire) < need) { - td::this_thread::yield(); + usleep_for(1); } }; @@ -139,6 +141,26 @@ class Stage { std::atomic value_{0}; }; +class StageMutex { + public: + void wait(uint64 need) { + std::unique_lock lock{mutex_}; + value_++; + if (value_ == need) { + cond_.notify_all(); + return; + } + cond_.wait(lock, [&] { return value_ >= need; }); + }; + + private: + std::mutex mutex_; + std::condition_variable cond_; + uint64 value_{0}; +}; + +using Stage = StageMutex; + string rand_string(int from, int to, size_t len); vector rand_split(Slice str);