1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_COMPOSITOR_PRIORITY_EXPERIMENTS_H_
6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_COMPOSITOR_PRIORITY_EXPERIMENTS_H_
7 
8 #include "base/task/sequence_manager/task_queue.h"
9 #include "third_party/blink/renderer/platform/platform_export.h"
10 #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
11 #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
12 #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h"
13 #include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
14 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
15 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
16 
17 namespace blink {
18 namespace scheduler {
19 
20 using TaskQueue = base::sequence_manager::TaskQueue;
21 using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority;
22 
23 class CPUTimeBudgetPool;
24 class MainThreadSchedulerImpl;
25 class MainThreadTaskQueue;
26 
27 class PLATFORM_EXPORT CompositorPriorityExperiments {
28   DISALLOW_NEW();
29 
30  public:
31   explicit CompositorPriorityExperiments(MainThreadSchedulerImpl* scheduler);
32   ~CompositorPriorityExperiments();
33 
34   enum class Experiment {
35     kNone,
36     kVeryHighPriorityForCompositingAlways,
37     kVeryHighPriorityForCompositingWhenFast,
38     kVeryHighPriorityForCompositingAlternating,
39     kVeryHighPriorityForCompositingAfterDelay,
40     kVeryHighPriorityForCompositingBudget
41   };
42 
43   bool IsExperimentActive() const;
44 
45   QueuePriority GetCompositorPriority() const;
46 
47   void OnTaskCompleted(MainThreadTaskQueue* queue,
48                        QueuePriority current_priority,
49                        MainThreadTaskQueue::TaskTiming* task_timing);
50 
GetAlternatingPriority()51   QueuePriority GetAlternatingPriority() const {
52     return alternating_compositor_priority_;
53   }
54 
55   void OnWillBeginMainFrame();
56 
57   void OnMainThreadSchedulerInitialized();
58   void OnMainThreadSchedulerShutdown();
59 
60   void OnBudgetExhausted();
61   void OnBudgetReplenished();
62 
63  private:
64   class CompositorBudgetPoolController : public BudgetPoolController {
65    public:
66     explicit CompositorBudgetPoolController(
67         CompositorPriorityExperiments* experiment,
68         MainThreadSchedulerImpl* scheduler,
69         MainThreadTaskQueue* compositor_queue,
70         TraceableVariableController* tracing_controller,
71         base::TimeDelta min_budget,
72         double budget_recovery_rate);
73     ~CompositorBudgetPoolController() override;
74 
75     void UpdateQueueSchedulingLifecycleState(base::TimeTicks now,
76                                              TaskQueue* queue) override;
77 
78     void UpdateCompositorBudgetState(base::TimeTicks now);
79 
80     void OnTaskCompleted(MainThreadTaskQueue* queue,
81                          MainThreadTaskQueue::TaskTiming* task_timing,
82                          bool have_seen_stop_signal);
83 
84     // Unimplemented methods.
AddQueueToBudgetPool(TaskQueue * queue,BudgetPool * budget_pool)85     void AddQueueToBudgetPool(TaskQueue* queue,
86                               BudgetPool* budget_pool) override {}
RemoveQueueFromBudgetPool(TaskQueue * queue,BudgetPool * budget_pool)87     void RemoveQueueFromBudgetPool(TaskQueue* queue,
88                                    BudgetPool* budget_pool) override {}
UnregisterBudgetPool(BudgetPool * budget_pool)89     void UnregisterBudgetPool(BudgetPool* budget_pool) override {}
IsThrottled(TaskQueue * queue)90     bool IsThrottled(TaskQueue* queue) const override { return false; }
91 
92    private:
93     CompositorPriorityExperiments* experiment_;
94     std::unique_ptr<CPUTimeBudgetPool> compositor_budget_pool_;
95     bool is_exhausted_ = false;
96   };
97 
98   static Experiment GetExperimentFromFeatureList();
99 
100   enum class StopSignalType { kAnyCompositorTask, kBeginMainFrameTask };
101 
102   MainThreadSchedulerImpl* scheduler_;  // Not owned.
103 
104   const Experiment experiment_;
105 
106   QueuePriority alternating_compositor_priority_ =
107       QueuePriority::kVeryHighPriority;
108 
109   QueuePriority delay_compositor_priority_ = QueuePriority::kNormalPriority;
110   base::TimeTicks last_compositor_task_time_;
111   base::TimeDelta prioritize_compositing_after_delay_length_;
112 
113   QueuePriority budget_compositor_priority_ = QueuePriority::kVeryHighPriority;
114   std::unique_ptr<CompositorBudgetPoolController> budget_pool_controller_;
115 
116   const StopSignalType stop_signal_;
117   bool will_begin_main_frame_ = false;
118 };
119 
120 }  // namespace scheduler
121 }  // namespace blink
122 
123 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_COMPOSITOR_PRIORITY_EXPERIMENTS_H_
124