From 57afb7f6e6acb93599066639032e3bd688ef1626 Mon Sep 17 00:00:00 2001 From: Justin Link Date: Tue, 22 Apr 2025 15:59:06 +0000 Subject: [PATCH] Bug 1959561: Implemented new TimerThread chaos mode wait time adjustment r=smaug Previously we would scale the wait time by a randomly selected factor, which meant that small waits would only ever get small (probably ineffective) adjustments. Now we randomly pick an adjustment in a known range and build our adjustment from that. This is simple, and doesn't require the costly, and otherwise unnecessary, conversion of a TimeStamp to microseconds. Differential Revision: https://phabricator.services.mozilla.com/D245678 --- mfbt/ChaosMode.h | 9 +++++++++ xpcom/threads/TimerThread.cpp | 23 ++++++++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mfbt/ChaosMode.h b/mfbt/ChaosMode.h index b4dba6cc6cd2..722a665d9a59 100644 --- a/mfbt/ChaosMode.h +++ b/mfbt/ChaosMode.h @@ -80,6 +80,15 @@ class ChaosMode { MOZ_ASSERT(aBound != 0); return uint32_t(rand()) % aBound; } + + /** + * Returns a somewhat (but not uniformly) random int32_t <= aLow and >= aHigh. + * Not to be used for anything except ChaosMode, since it's not very random. + */ + static int32_t randomInt32InRange(int32_t aLow, int32_t aHigh) { + MOZ_ASSERT(aHigh >= aLow); + return (int32_t(rand()) % (aHigh - aLow + 1)) + aLow; + } }; } /* namespace mozilla */ diff --git a/xpcom/threads/TimerThread.cpp b/xpcom/threads/TimerThread.cpp index 617d65dc9604..002d7cd8cbac 100644 --- a/xpcom/threads/TimerThread.cpp +++ b/xpcom/threads/TimerThread.cpp @@ -878,11 +878,6 @@ TimerThread::Run() { // interval is so small we should not wait at all). const TimeDuration timeToNextTimer = timeout - now; - // The mean value of sFractions must be 1 to ensure that the average of - // a long sequence of timeouts converges to the actual sum of their - // times. - static constexpr double sChaosFractions[] = {0.0, 0.25, 0.5, 0.75, - 1.0, 1.75, 2.75}; if (timeToNextTimer < allowedEarlyFiring) { goto next; // round down; execute event now } @@ -903,16 +898,14 @@ TimerThread::Run() { // should have fired. MOZ_ASSERT(!waitFor.IsZero()); - if (chaosModeActive) { - // If chaos mode is active then mess with the amount of time that we - // request to sleep (without changing what we record as our expected - // wake-up time). This will simulate unintended early/late wake-ups. - const double waitInMs = waitFor.ToMilliseconds(); - const double chaosWaitInMs = - waitInMs * sChaosFractions[ChaosMode::randomUint32LessThan( - std::size(sChaosFractions))]; - waitFor = TimeDuration::FromMilliseconds(chaosWaitInMs); - } + // If chaos mode is active then we will add a random amount to the + // calculated wait (sleep) time to simulate early/late wake-ups. + const TimeDuration chaosWaitDelay = + !chaosModeActive + ? TimeDuration::Zero() + : TimeDuration::FromMicroseconds( + ChaosMode::randomInt32InRange(-10000, 10000)); + waitFor = std::max(TimeDuration::Zero(), waitFor + chaosWaitDelay); mIntendedWakeupTime = wakeupTime; } else {