OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/scheduler/compositor_timing_history.h" | 5 #include "cc/scheduler/compositor_timing_history.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "base/trace_event/trace_event.h" | 8 #include "base/trace_event/trace_event.h" |
9 #include "cc/debug/rendering_stats_instrumentation.h" | 9 #include "cc/debug/rendering_stats_instrumentation.h" |
10 | 10 |
| 11 // The estimates that affect the compositors deadline use the 100th percentile |
| 12 // to avoid missing the Browser's deadline. |
| 13 // The estimates related to main-thread responsiveness affect whether |
| 14 // we attempt to recovery latency or not and use the 50th percentile. |
| 15 // TODO(brianderson): Fine tune the percentiles below. |
11 const size_t kDurationHistorySize = 60; | 16 const size_t kDurationHistorySize = 60; |
12 const double kCommitAndActivationDurationEstimationPercentile = 50.0; | 17 const double kBeginMainFrameToCommitEstimationPercentile = 50.0; |
13 const double kDrawDurationEstimationPercentile = 100.0; | 18 const double kCommitToReadyToActivateEstimationPercentile = 50.0; |
14 const int kDrawDurationEstimatePaddingInMicroseconds = 0; | 19 const double kPrepareTilesEstimationPercentile = 100.0; |
| 20 const double kActivateEstimationPercentile = 100.0; |
| 21 const double kDrawEstimationPercentile = 100.0; |
15 | 22 |
16 namespace cc { | 23 namespace cc { |
17 | 24 |
18 CompositorTimingHistory::CompositorTimingHistory( | 25 CompositorTimingHistory::CompositorTimingHistory( |
19 RenderingStatsInstrumentation* rendering_stats_instrumentation) | 26 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
20 : draw_duration_history_(kDurationHistorySize), | 27 : enabled_(false), |
21 begin_main_frame_to_commit_duration_history_(kDurationHistorySize), | 28 begin_main_frame_to_commit_duration_history_(kDurationHistorySize), |
22 commit_to_activate_duration_history_(kDurationHistorySize), | 29 commit_to_ready_to_activate_duration_history_(kDurationHistorySize), |
| 30 prepare_tiles_duration_history_(kDurationHistorySize), |
| 31 activate_duration_history_(kDurationHistorySize), |
| 32 draw_duration_history_(kDurationHistorySize), |
23 rendering_stats_instrumentation_(rendering_stats_instrumentation) { | 33 rendering_stats_instrumentation_(rendering_stats_instrumentation) { |
24 } | 34 } |
25 | 35 |
26 CompositorTimingHistory::~CompositorTimingHistory() { | 36 CompositorTimingHistory::~CompositorTimingHistory() { |
27 } | 37 } |
28 | 38 |
29 void CompositorTimingHistory::AsValueInto( | 39 void CompositorTimingHistory::AsValueInto( |
30 base::trace_event::TracedValue* state) const { | 40 base::trace_event::TracedValue* state) const { |
31 state->SetDouble("begin_main_frame_to_commit_duration_estimate_ms", | 41 state->SetDouble("begin_main_frame_to_commit_duration_estimate_ms", |
32 BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); | 42 BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); |
33 state->SetDouble("commit_to_activate_duration_estimate_ms", | 43 state->SetDouble("commit_to_ready_to_activate_duration_estimate_ms", |
34 CommitToActivateDurationEstimate().InMillisecondsF()); | 44 CommitToReadyToActivateDurationEstimate().InMillisecondsF()); |
| 45 state->SetDouble("prepare_tiles_duration_estimate_ms", |
| 46 PrepareTilesDurationEstimate().InMillisecondsF()); |
| 47 state->SetDouble("activate_duration_estimate_ms", |
| 48 ActivateDurationEstimate().InMillisecondsF()); |
35 state->SetDouble("draw_duration_estimate_ms", | 49 state->SetDouble("draw_duration_estimate_ms", |
36 DrawDurationEstimate().InMillisecondsF()); | 50 DrawDurationEstimate().InMillisecondsF()); |
37 } | 51 } |
38 | 52 |
39 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { | 53 base::TimeTicks CompositorTimingHistory::Now() const { |
40 base::TimeDelta historical_estimate = | 54 return base::TimeTicks::Now(); |
41 draw_duration_history_.Percentile(kDrawDurationEstimationPercentile); | 55 } |
42 base::TimeDelta padding = base::TimeDelta::FromMicroseconds( | 56 |
43 kDrawDurationEstimatePaddingInMicroseconds); | 57 void CompositorTimingHistory::SetRecordingEnabled(bool enabled) { |
44 return historical_estimate + padding; | 58 enabled_ = enabled; |
45 } | 59 } |
46 | 60 |
47 base::TimeDelta | 61 base::TimeDelta |
48 CompositorTimingHistory::BeginMainFrameToCommitDurationEstimate() const { | 62 CompositorTimingHistory::BeginMainFrameToCommitDurationEstimate() const { |
49 return begin_main_frame_to_commit_duration_history_.Percentile( | 63 return begin_main_frame_to_commit_duration_history_.Percentile( |
50 kCommitAndActivationDurationEstimationPercentile); | 64 kBeginMainFrameToCommitEstimationPercentile); |
51 } | 65 } |
52 | 66 |
53 base::TimeDelta CompositorTimingHistory::CommitToActivateDurationEstimate() | 67 base::TimeDelta |
54 const { | 68 CompositorTimingHistory::CommitToReadyToActivateDurationEstimate() const { |
55 return commit_to_activate_duration_history_.Percentile( | 69 return commit_to_ready_to_activate_duration_history_.Percentile( |
56 kCommitAndActivationDurationEstimationPercentile); | 70 kCommitToReadyToActivateEstimationPercentile); |
| 71 } |
| 72 |
| 73 base::TimeDelta CompositorTimingHistory::PrepareTilesDurationEstimate() const { |
| 74 return prepare_tiles_duration_history_.Percentile( |
| 75 kPrepareTilesEstimationPercentile); |
| 76 } |
| 77 |
| 78 base::TimeDelta CompositorTimingHistory::ActivateDurationEstimate() const { |
| 79 return activate_duration_history_.Percentile(kActivateEstimationPercentile); |
| 80 } |
| 81 |
| 82 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { |
| 83 return draw_duration_history_.Percentile(kDrawEstimationPercentile); |
57 } | 84 } |
58 | 85 |
59 void CompositorTimingHistory::WillBeginMainFrame() { | 86 void CompositorTimingHistory::WillBeginMainFrame() { |
60 begin_main_frame_sent_time_ = base::TimeTicks::Now(); | 87 DCHECK_EQ(base::TimeTicks(), begin_main_frame_sent_time_); |
| 88 begin_main_frame_sent_time_ = Now(); |
| 89 } |
| 90 |
| 91 void CompositorTimingHistory::BeginMainFrameAborted() { |
| 92 DidCommit(); |
61 } | 93 } |
62 | 94 |
63 void CompositorTimingHistory::DidCommit() { | 95 void CompositorTimingHistory::DidCommit() { |
64 commit_complete_time_ = base::TimeTicks::Now(); | 96 DCHECK_NE(base::TimeTicks(), begin_main_frame_sent_time_); |
| 97 |
| 98 commit_time_ = Now(); |
| 99 |
65 base::TimeDelta begin_main_frame_to_commit_duration = | 100 base::TimeDelta begin_main_frame_to_commit_duration = |
66 commit_complete_time_ - begin_main_frame_sent_time_; | 101 commit_time_ - begin_main_frame_sent_time_; |
67 | 102 |
68 // Before adding the new data point to the timing history, see what we would | 103 // Before adding the new data point to the timing history, see what we would |
69 // have predicted for this frame. This allows us to keep track of the accuracy | 104 // have predicted for this frame. This allows us to keep track of the accuracy |
70 // of our predictions. | 105 // of our predictions. |
71 rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration( | 106 rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration( |
72 begin_main_frame_to_commit_duration, | 107 begin_main_frame_to_commit_duration, |
73 BeginMainFrameToCommitDurationEstimate()); | 108 BeginMainFrameToCommitDurationEstimate()); |
74 | 109 |
75 begin_main_frame_to_commit_duration_history_.InsertSample( | 110 if (enabled_) { |
76 begin_main_frame_to_commit_duration); | 111 begin_main_frame_to_commit_duration_history_.InsertSample( |
| 112 begin_main_frame_to_commit_duration); |
| 113 } |
| 114 |
| 115 begin_main_frame_sent_time_ = base::TimeTicks(); |
77 } | 116 } |
78 | 117 |
79 void CompositorTimingHistory::DidActivateSyncTree() { | 118 void CompositorTimingHistory::WillPrepareTiles() { |
80 base::TimeDelta commit_to_activate_duration = | 119 DCHECK_EQ(base::TimeTicks(), start_prepare_tiles_time_); |
81 base::TimeTicks::Now() - commit_complete_time_; | 120 start_prepare_tiles_time_ = Now(); |
| 121 } |
| 122 |
| 123 void CompositorTimingHistory::DidPrepareTiles() { |
| 124 DCHECK_NE(base::TimeTicks(), start_prepare_tiles_time_); |
| 125 |
| 126 if (enabled_) { |
| 127 base::TimeDelta prepare_tiles_duration = Now() - start_prepare_tiles_time_; |
| 128 prepare_tiles_duration_history_.InsertSample(prepare_tiles_duration); |
| 129 } |
| 130 |
| 131 start_prepare_tiles_time_ = base::TimeTicks(); |
| 132 } |
| 133 |
| 134 void CompositorTimingHistory::ReadyToActivate() { |
| 135 // We only care about the first ready to activate signal |
| 136 // after a commit. |
| 137 if (commit_time_ == base::TimeTicks()) |
| 138 return; |
| 139 |
| 140 base::TimeDelta time_since_commit = Now() - commit_time_; |
82 | 141 |
83 // Before adding the new data point to the timing history, see what we would | 142 // Before adding the new data point to the timing history, see what we would |
84 // have predicted for this frame. This allows us to keep track of the accuracy | 143 // have predicted for this frame. This allows us to keep track of the accuracy |
85 // of our predictions. | 144 // of our predictions. |
86 rendering_stats_instrumentation_->AddCommitToActivateDuration( | 145 rendering_stats_instrumentation_->AddCommitToActivateDuration( |
87 commit_to_activate_duration, CommitToActivateDurationEstimate()); | 146 time_since_commit, CommitToReadyToActivateDurationEstimate()); |
88 | 147 |
89 commit_to_activate_duration_history_.InsertSample( | 148 if (enabled_) { |
90 commit_to_activate_duration); | 149 commit_to_ready_to_activate_duration_history_.InsertSample( |
| 150 time_since_commit); |
| 151 } |
| 152 |
| 153 commit_time_ = base::TimeTicks(); |
91 } | 154 } |
92 | 155 |
93 void CompositorTimingHistory::DidStartDrawing() { | 156 void CompositorTimingHistory::WillActivate() { |
94 start_draw_time_ = base::TimeTicks::Now(); | 157 DCHECK_EQ(base::TimeTicks(), start_activate_time_); |
| 158 start_activate_time_ = Now(); |
95 } | 159 } |
96 | 160 |
97 void CompositorTimingHistory::DidFinishDrawing() { | 161 void CompositorTimingHistory::DidActivate() { |
98 base::TimeDelta draw_duration = base::TimeTicks::Now() - start_draw_time_; | 162 DCHECK_NE(base::TimeTicks(), start_activate_time_); |
| 163 if (enabled_) { |
| 164 base::TimeDelta activate_duration = Now() - start_activate_time_; |
| 165 activate_duration_history_.InsertSample(activate_duration); |
| 166 } |
| 167 start_activate_time_ = base::TimeTicks(); |
| 168 } |
| 169 |
| 170 void CompositorTimingHistory::WillDraw() { |
| 171 DCHECK_EQ(base::TimeTicks(), start_draw_time_); |
| 172 start_draw_time_ = Now(); |
| 173 } |
| 174 |
| 175 void CompositorTimingHistory::DidDraw() { |
| 176 DCHECK_NE(base::TimeTicks(), start_draw_time_); |
| 177 base::TimeDelta draw_duration = Now() - start_draw_time_; |
99 | 178 |
100 // Before adding the new data point to the timing history, see what we would | 179 // Before adding the new data point to the timing history, see what we would |
101 // have predicted for this frame. This allows us to keep track of the accuracy | 180 // have predicted for this frame. This allows us to keep track of the accuracy |
102 // of our predictions. | 181 // of our predictions. |
103 base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); | 182 base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); |
104 rendering_stats_instrumentation_->AddDrawDuration(draw_duration, | 183 rendering_stats_instrumentation_->AddDrawDuration(draw_duration, |
105 draw_duration_estimate); | 184 draw_duration_estimate); |
106 | 185 |
107 AddDrawDurationUMA(draw_duration, draw_duration_estimate); | 186 AddDrawDurationUMA(draw_duration, draw_duration_estimate); |
108 | 187 |
109 draw_duration_history_.InsertSample(draw_duration); | 188 if (enabled_) { |
| 189 draw_duration_history_.InsertSample(draw_duration); |
| 190 } |
| 191 |
| 192 start_draw_time_ = base::TimeTicks(); |
110 } | 193 } |
111 | 194 |
112 void CompositorTimingHistory::AddDrawDurationUMA( | 195 void CompositorTimingHistory::AddDrawDurationUMA( |
113 base::TimeDelta draw_duration, | 196 base::TimeDelta draw_duration, |
114 base::TimeDelta draw_duration_estimate) { | 197 base::TimeDelta draw_duration_estimate) { |
115 base::TimeDelta draw_duration_overestimate; | 198 base::TimeDelta draw_duration_overestimate; |
116 base::TimeDelta draw_duration_underestimate; | 199 base::TimeDelta draw_duration_underestimate; |
117 if (draw_duration > draw_duration_estimate) | 200 if (draw_duration > draw_duration_estimate) |
118 draw_duration_underestimate = draw_duration - draw_duration_estimate; | 201 draw_duration_underestimate = draw_duration - draw_duration_estimate; |
119 else | 202 else |
120 draw_duration_overestimate = draw_duration_estimate - draw_duration; | 203 draw_duration_overestimate = draw_duration_estimate - draw_duration; |
121 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", draw_duration, | 204 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", draw_duration, |
122 base::TimeDelta::FromMilliseconds(1), | 205 base::TimeDelta::FromMilliseconds(1), |
123 base::TimeDelta::FromMilliseconds(100), 50); | 206 base::TimeDelta::FromMilliseconds(100), 50); |
124 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", | 207 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", |
125 draw_duration_underestimate, | 208 draw_duration_underestimate, |
126 base::TimeDelta::FromMilliseconds(1), | 209 base::TimeDelta::FromMilliseconds(1), |
127 base::TimeDelta::FromMilliseconds(100), 50); | 210 base::TimeDelta::FromMilliseconds(100), 50); |
128 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", | 211 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", |
129 draw_duration_overestimate, | 212 draw_duration_overestimate, |
130 base::TimeDelta::FromMilliseconds(1), | 213 base::TimeDelta::FromMilliseconds(1), |
131 base::TimeDelta::FromMilliseconds(100), 50); | 214 base::TimeDelta::FromMilliseconds(100), 50); |
132 } | 215 } |
133 | 216 |
134 } // namespace cc | 217 } // namespace cc |
OLD | NEW |