1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "MainThreadIdlePeriod.h"
8 
9 #include "mozilla/Maybe.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/StaticPrefs_idle_period.h"
12 #include "mozilla/dom/Document.h"
13 #include "VRManagerChild.h"
14 #include "nsRefreshDriver.h"
15 #include "nsThreadUtils.h"
16 
17 // The amount of idle time (milliseconds) reserved for a long idle period.
18 static const double kLongIdlePeriodMS = 50.0;
19 
20 // The minimum amount of time (milliseconds) required for an idle period to be
21 // scheduled on the main thread. N.B. layout.idle_period.time_limit adds
22 // padding at the end of the idle period, which makes the point in time that we
23 // expect to become busy again be:
24 //   now + idle_period.min + layout.idle_period.time_limit
25 // or during page load
26 //   now + idle_period.during_page_load.min + layout.idle_period.time_limit
27 
28 static const uint32_t kMaxTimerThreadBound = 5;        // milliseconds
29 static const uint32_t kMaxTimerThreadBoundClamp = 15;  // milliseconds
30 
31 namespace mozilla {
32 
33 NS_IMETHODIMP
GetIdlePeriodHint(TimeStamp * aIdleDeadline)34 MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) {
35   MOZ_ASSERT(NS_IsMainThread());
36   MOZ_ASSERT(aIdleDeadline);
37 
38   TimeStamp now = TimeStamp::Now();
39   TimeStamp currentGuess =
40       now + TimeDuration::FromMilliseconds(kLongIdlePeriodMS);
41 
42   currentGuess = nsRefreshDriver::GetIdleDeadlineHint(currentGuess);
43   if (XRE_IsContentProcess()) {
44     currentGuess = gfx::VRManagerChild::GetIdleDeadlineHint(currentGuess);
45   }
46   currentGuess = NS_GetTimerDeadlineHintOnCurrentThread(currentGuess,
47                                                         kMaxTimerThreadBound);
48 
49   // If the idle period is too small, then just return a null time
50   // to indicate we are busy. Otherwise return the actual deadline.
51   TimeDuration minIdlePeriod =
52       TimeDuration::FromMilliseconds(StaticPrefs::idle_period_min());
53   bool busySoon = currentGuess.IsNull() ||
54                   (now >= (currentGuess - minIdlePeriod)) ||
55                   currentGuess < mLastIdleDeadline;
56 
57   // During page load use higher minimum idle period.
58   if (!busySoon && XRE_IsContentProcess() &&
59       mozilla::dom::Document::HasRecentlyStartedForegroundLoads()) {
60     TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds(
61         StaticPrefs::idle_period_during_page_load_min());
62     busySoon = (now >= (currentGuess - minIdlePeriod));
63   }
64 
65   if (!busySoon) {
66     *aIdleDeadline = mLastIdleDeadline = currentGuess;
67   }
68 
69   return NS_OK;
70 }
71 
72 /* static */
GetLongIdlePeriod()73 float MainThreadIdlePeriod::GetLongIdlePeriod() { return kLongIdlePeriodMS; }
74 
75 }  // namespace mozilla
76