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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 base::TimeDelta duration) = 0; | 30 base::TimeDelta duration) = 0; |
31 virtual void AddBeginMainFrameQueueDurationNotCriticalDuration( | 31 virtual void AddBeginMainFrameQueueDurationNotCriticalDuration( |
32 base::TimeDelta duration) = 0; | 32 base::TimeDelta duration) = 0; |
33 virtual void AddBeginMainFrameStartToCommitDuration( | 33 virtual void AddBeginMainFrameStartToCommitDuration( |
34 base::TimeDelta duration) = 0; | 34 base::TimeDelta duration) = 0; |
35 virtual void AddCommitToReadyToActivateDuration(base::TimeDelta duration) = 0; | 35 virtual void AddCommitToReadyToActivateDuration(base::TimeDelta duration) = 0; |
36 virtual void AddPrepareTilesDuration(base::TimeDelta duration) = 0; | 36 virtual void AddPrepareTilesDuration(base::TimeDelta duration) = 0; |
37 virtual void AddActivateDuration(base::TimeDelta duration) = 0; | 37 virtual void AddActivateDuration(base::TimeDelta duration) = 0; |
38 virtual void AddDrawDuration(base::TimeDelta duration) = 0; | 38 virtual void AddDrawDuration(base::TimeDelta duration) = 0; |
39 virtual void AddSwapToAckLatency(base::TimeDelta duration) = 0; | 39 virtual void AddSwapToAckLatency(base::TimeDelta duration) = 0; |
40 virtual void AddSwapAckWasFast(bool was_fast) = 0; | |
40 | 41 |
41 // Synchronization measurements | 42 // Synchronization measurements |
42 virtual void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) = 0; | 43 virtual void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) = 0; |
43 }; | 44 }; |
44 | 45 |
45 namespace { | 46 namespace { |
46 | 47 |
47 // Using the 90th percentile will disable latency recovery | 48 // Using the 90th percentile will disable latency recovery |
48 // if we are missing the deadline approximately ~6 times per | 49 // if we are missing the deadline approximately ~6 times per |
49 // second. | 50 // second. |
50 // TODO(brianderson): Fine tune the percentiles below. | 51 // TODO(brianderson): Fine tune the percentiles below. |
51 const size_t kDurationHistorySize = 60; | 52 const size_t kDurationHistorySize = 60; |
52 const double kBeginMainFrameQueueDurationEstimationPercentile = 90.0; | 53 const double kBeginMainFrameQueueDurationEstimationPercentile = 90.0; |
53 const double kBeginMainFrameQueueDurationCriticalEstimationPercentile = 90.0; | 54 const double kBeginMainFrameQueueDurationCriticalEstimationPercentile = 90.0; |
54 const double kBeginMainFrameQueueDurationNotCriticalEstimationPercentile = 90.0; | 55 const double kBeginMainFrameQueueDurationNotCriticalEstimationPercentile = 90.0; |
55 const double kBeginMainFrameStartToCommitEstimationPercentile = 90.0; | 56 const double kBeginMainFrameStartToCommitEstimationPercentile = 90.0; |
56 const double kCommitToReadyToActivateEstimationPercentile = 90.0; | 57 const double kCommitToReadyToActivateEstimationPercentile = 90.0; |
57 const double kPrepareTilesEstimationPercentile = 90.0; | 58 const double kPrepareTilesEstimationPercentile = 90.0; |
58 const double kActivateEstimationPercentile = 90.0; | 59 const double kActivateEstimationPercentile = 90.0; |
59 const double kDrawEstimationPercentile = 90.0; | 60 const double kDrawEstimationPercentile = 90.0; |
60 | 61 |
62 // The watchdog uses a combination of BeginImplFrame counts and | |
63 // actual timestamps to avoid calling Now() too often or adding | |
sunnyps
2016/08/30 18:31:04
Is this optimization really needed? Even without t
brianderson
2016/08/30 22:30:32
A few years ago, we were especially concerned abou
| |
64 // unnecessary idle wakeups. | |
65 // This will break if we aren't receiving BeginFrames, but this | |
66 // is primarily for crbug.com/602486, where we are receiving them. | |
67 const int kSwapAckWatchdogBeginImplFrameCount = 8 * 61; | |
68 const int kSwapAckWatchdogBeginImplFrameReCount = 60; | |
69 const base::TimeDelta kSwapAckWatchdogTimeout = | |
70 base::TimeDelta::FromMicroseconds(8000000); | |
71 | |
61 const int kUmaDurationMinMicros = 1; | 72 const int kUmaDurationMinMicros = 1; |
62 const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5; | 73 const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5; |
63 const int kUmaDurationBucketCount = 100; | 74 const int kUmaDurationBucketCount = 100; |
64 | 75 |
65 // This macro is deprecated since its bucket count uses too much bandwidth. | 76 // This macro is deprecated since its bucket count uses too much bandwidth. |
66 // It also has sub-optimal range and bucket distribution. | 77 // It also has sub-optimal range and bucket distribution. |
67 // TODO(brianderson): Delete this macro and associated UMAs once there is | 78 // TODO(brianderson): Delete this macro and associated UMAs once there is |
68 // sufficient overlap with the re-bucketed UMAs. | 79 // sufficient overlap with the re-bucketed UMAs. |
69 #define UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample) \ | 80 #define UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample) \ |
70 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample.InMicroseconds(), \ | 81 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample.InMicroseconds(), \ |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 void AddDrawDuration(base::TimeDelta duration) override { | 195 void AddDrawDuration(base::TimeDelta duration) override { |
185 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.DrawDuration", | 196 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.DrawDuration", |
186 duration); | 197 duration); |
187 } | 198 } |
188 | 199 |
189 void AddSwapToAckLatency(base::TimeDelta duration) override { | 200 void AddSwapToAckLatency(base::TimeDelta duration) override { |
190 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.SwapToAckLatency", | 201 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.SwapToAckLatency", |
191 duration); | 202 duration); |
192 } | 203 } |
193 | 204 |
205 void AddSwapAckWasFast(bool was_fast) override { | |
206 UMA_HISTOGRAM_BOOLEAN("Scheduling.Renderer.SwapAckWasFast", was_fast); | |
207 } | |
208 | |
194 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override { | 209 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override { |
195 UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( | 210 UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( |
196 "Scheduling.Renderer.MainAndImplFrameTimeDelta", delta); | 211 "Scheduling.Renderer.MainAndImplFrameTimeDelta", delta); |
197 } | 212 } |
198 }; | 213 }; |
199 | 214 |
200 class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter { | 215 class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter { |
201 public: | 216 public: |
202 ~BrowserUMAReporter() override {} | 217 ~BrowserUMAReporter() override {} |
203 | 218 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 void AddDrawDuration(base::TimeDelta duration) override { | 272 void AddDrawDuration(base::TimeDelta duration) override { |
258 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.DrawDuration", | 273 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.DrawDuration", |
259 duration); | 274 duration); |
260 } | 275 } |
261 | 276 |
262 void AddSwapToAckLatency(base::TimeDelta duration) override { | 277 void AddSwapToAckLatency(base::TimeDelta duration) override { |
263 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.SwapToAckLatency", | 278 UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.SwapToAckLatency", |
264 duration); | 279 duration); |
265 } | 280 } |
266 | 281 |
282 void AddSwapAckWasFast(bool was_fast) override { | |
283 UMA_HISTOGRAM_BOOLEAN("Scheduling.Browser.SwapAckWasFast", was_fast); | |
284 } | |
285 | |
267 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override { | 286 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override { |
268 UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( | 287 UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( |
269 "Scheduling.Browser.MainAndImplFrameTimeDelta", delta); | 288 "Scheduling.Browser.MainAndImplFrameTimeDelta", delta); |
270 } | 289 } |
271 }; | 290 }; |
272 | 291 |
273 class NullUMAReporter : public CompositorTimingHistory::UMAReporter { | 292 class NullUMAReporter : public CompositorTimingHistory::UMAReporter { |
274 public: | 293 public: |
275 ~NullUMAReporter() override {} | 294 ~NullUMAReporter() override {} |
276 void AddBeginMainFrameIntervalCritical(base::TimeDelta interval) override {} | 295 void AddBeginMainFrameIntervalCritical(base::TimeDelta interval) override {} |
277 void AddBeginMainFrameIntervalNotCritical(base::TimeDelta interval) override { | 296 void AddBeginMainFrameIntervalNotCritical(base::TimeDelta interval) override { |
278 } | 297 } |
279 void AddCommitInterval(base::TimeDelta interval) override {} | 298 void AddCommitInterval(base::TimeDelta interval) override {} |
280 void AddDrawInterval(base::TimeDelta interval) override {} | 299 void AddDrawInterval(base::TimeDelta interval) override {} |
281 void AddBeginMainFrameQueueDurationCriticalDuration( | 300 void AddBeginMainFrameQueueDurationCriticalDuration( |
282 base::TimeDelta duration) override {} | 301 base::TimeDelta duration) override {} |
283 void AddBeginMainFrameQueueDurationNotCriticalDuration( | 302 void AddBeginMainFrameQueueDurationNotCriticalDuration( |
284 base::TimeDelta duration) override {} | 303 base::TimeDelta duration) override {} |
285 void AddBeginMainFrameStartToCommitDuration( | 304 void AddBeginMainFrameStartToCommitDuration( |
286 base::TimeDelta duration) override {} | 305 base::TimeDelta duration) override {} |
287 void AddCommitToReadyToActivateDuration(base::TimeDelta duration) override {} | 306 void AddCommitToReadyToActivateDuration(base::TimeDelta duration) override {} |
288 void AddPrepareTilesDuration(base::TimeDelta duration) override {} | 307 void AddPrepareTilesDuration(base::TimeDelta duration) override {} |
289 void AddActivateDuration(base::TimeDelta duration) override {} | 308 void AddActivateDuration(base::TimeDelta duration) override {} |
290 void AddDrawDuration(base::TimeDelta duration) override {} | 309 void AddDrawDuration(base::TimeDelta duration) override {} |
291 void AddSwapToAckLatency(base::TimeDelta duration) override {} | 310 void AddSwapToAckLatency(base::TimeDelta duration) override {} |
311 void AddSwapAckWasFast(bool was_fast) override {} | |
292 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} | 312 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} |
293 }; | 313 }; |
294 | 314 |
295 } // namespace | 315 } // namespace |
296 | 316 |
297 CompositorTimingHistory::CompositorTimingHistory( | 317 CompositorTimingHistory::CompositorTimingHistory( |
298 bool using_synchronous_renderer_compositor, | 318 bool using_synchronous_renderer_compositor, |
299 UMACategory uma_category, | 319 UMACategory uma_category, |
300 RenderingStatsInstrumentation* rendering_stats_instrumentation) | 320 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
301 : using_synchronous_renderer_compositor_( | 321 : using_synchronous_renderer_compositor_( |
302 using_synchronous_renderer_compositor), | 322 using_synchronous_renderer_compositor), |
303 enabled_(false), | 323 enabled_(false), |
304 did_send_begin_main_frame_(false), | 324 did_send_begin_main_frame_(false), |
305 begin_main_frame_needed_continuously_(false), | 325 begin_main_frame_needed_continuously_(false), |
306 begin_main_frame_committing_continuously_(false), | 326 begin_main_frame_committing_continuously_(false), |
307 compositor_drawing_continuously_(false), | 327 compositor_drawing_continuously_(false), |
308 begin_main_frame_queue_duration_history_(kDurationHistorySize), | 328 begin_main_frame_queue_duration_history_(kDurationHistorySize), |
309 begin_main_frame_queue_duration_critical_history_(kDurationHistorySize), | 329 begin_main_frame_queue_duration_critical_history_(kDurationHistorySize), |
310 begin_main_frame_queue_duration_not_critical_history_( | 330 begin_main_frame_queue_duration_not_critical_history_( |
311 kDurationHistorySize), | 331 kDurationHistorySize), |
312 begin_main_frame_start_to_commit_duration_history_(kDurationHistorySize), | 332 begin_main_frame_start_to_commit_duration_history_(kDurationHistorySize), |
313 commit_to_ready_to_activate_duration_history_(kDurationHistorySize), | 333 commit_to_ready_to_activate_duration_history_(kDurationHistorySize), |
314 prepare_tiles_duration_history_(kDurationHistorySize), | 334 prepare_tiles_duration_history_(kDurationHistorySize), |
315 activate_duration_history_(kDurationHistorySize), | 335 activate_duration_history_(kDurationHistorySize), |
316 draw_duration_history_(kDurationHistorySize), | 336 draw_duration_history_(kDurationHistorySize), |
317 begin_main_frame_on_critical_path_(false), | 337 begin_main_frame_on_critical_path_(false), |
338 swap_ack_watchdog_enabled_(false), | |
339 swap_ack_watchdog_begin_impl_frame_count_(0), | |
318 uma_reporter_(CreateUMAReporter(uma_category)), | 340 uma_reporter_(CreateUMAReporter(uma_category)), |
319 rendering_stats_instrumentation_(rendering_stats_instrumentation) {} | 341 rendering_stats_instrumentation_(rendering_stats_instrumentation) {} |
320 | 342 |
321 CompositorTimingHistory::~CompositorTimingHistory() { | 343 CompositorTimingHistory::~CompositorTimingHistory() { |
322 } | 344 } |
323 | 345 |
324 std::unique_ptr<CompositorTimingHistory::UMAReporter> | 346 std::unique_ptr<CompositorTimingHistory::UMAReporter> |
325 CompositorTimingHistory::CreateUMAReporter(UMACategory category) { | 347 CompositorTimingHistory::CreateUMAReporter(UMACategory category) { |
326 switch (category) { | 348 switch (category) { |
327 case RENDERER_UMA: | 349 case RENDERER_UMA: |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 } | 458 } |
437 | 459 |
438 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { | 460 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { |
439 return draw_duration_history_.Percentile(kDrawEstimationPercentile); | 461 return draw_duration_history_.Percentile(kDrawEstimationPercentile); |
440 } | 462 } |
441 | 463 |
442 void CompositorTimingHistory::DidCreateAndInitializeOutputSurface() { | 464 void CompositorTimingHistory::DidCreateAndInitializeOutputSurface() { |
443 // After we get a new output surface, we won't get a spurious | 465 // After we get a new output surface, we won't get a spurious |
444 // swap ack from the old output surface. | 466 // swap ack from the old output surface. |
445 swap_start_time_ = base::TimeTicks(); | 467 swap_start_time_ = base::TimeTicks(); |
468 swap_ack_watchdog_enabled_ = false; | |
469 swap_ack_watchdog_begin_impl_frame_count_ = 0; | |
446 } | 470 } |
447 | 471 |
448 void CompositorTimingHistory::WillBeginImplFrame( | 472 void CompositorTimingHistory::WillBeginImplFrame( |
449 bool new_active_tree_is_likely) { | 473 bool new_active_tree_is_likely) { |
450 // The check for whether a BeginMainFrame was sent anytime between two | 474 // The check for whether a BeginMainFrame was sent anytime between two |
451 // BeginImplFrames protects us from not detecting a fast main thread that | 475 // BeginImplFrames protects us from not detecting a fast main thread that |
452 // does all it's work and goes idle in between BeginImplFrames. | 476 // does all it's work and goes idle in between BeginImplFrames. |
453 // For example, this may happen if an animation is being driven with | 477 // For example, this may happen if an animation is being driven with |
454 // setInterval(17) or if input events just happen to arrive in the | 478 // setInterval(17) or if input events just happen to arrive in the |
455 // middle of every frame. | 479 // middle of every frame. |
456 if (!new_active_tree_is_likely && !did_send_begin_main_frame_) { | 480 if (!new_active_tree_is_likely && !did_send_begin_main_frame_) { |
457 SetBeginMainFrameNeededContinuously(false); | 481 SetBeginMainFrameNeededContinuously(false); |
458 SetBeginMainFrameCommittingContinuously(false); | 482 SetBeginMainFrameCommittingContinuously(false); |
459 } | 483 } |
460 | 484 |
485 // After N BeginImplFrames, check if the swap ack is taking too long. | |
486 // Otherwise, check again in M BeginImplFrames. | |
487 if (swap_ack_watchdog_enabled_) { | |
488 swap_ack_watchdog_begin_impl_frame_count_++; | |
489 if (swap_ack_watchdog_begin_impl_frame_count_ == | |
490 kSwapAckWatchdogBeginImplFrameCount) { | |
491 base::TimeDelta swap_not_acked_time_ = Now() - swap_start_time_; | |
492 if (swap_not_acked_time_ > kSwapAckWatchdogTimeout) { | |
493 uma_reporter_->AddSwapAckWasFast(false); | |
494 // Only record this UMA once per swap. | |
495 swap_ack_watchdog_enabled_ = false; | |
496 } else { | |
497 swap_ack_watchdog_begin_impl_frame_count_ -= | |
498 kSwapAckWatchdogBeginImplFrameReCount; | |
499 } | |
500 } | |
501 } | |
502 | |
461 did_send_begin_main_frame_ = false; | 503 did_send_begin_main_frame_ = false; |
462 } | 504 } |
463 | 505 |
464 void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw) { | 506 void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw) { |
465 if (!needs_redraw) | 507 if (!needs_redraw) |
466 SetCompositorDrawingContinuously(false); | 508 SetCompositorDrawingContinuously(false); |
467 } | 509 } |
468 | 510 |
469 void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() { | 511 void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() { |
470 SetBeginMainFrameNeededContinuously(false); | 512 SetBeginMainFrameNeededContinuously(false); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
690 new_active_tree_draw_end_time_prev_ = draw_end_time; | 732 new_active_tree_draw_end_time_prev_ = draw_end_time; |
691 } | 733 } |
692 } | 734 } |
693 | 735 |
694 draw_start_time_ = base::TimeTicks(); | 736 draw_start_time_ = base::TimeTicks(); |
695 } | 737 } |
696 | 738 |
697 void CompositorTimingHistory::DidSwapBuffers() { | 739 void CompositorTimingHistory::DidSwapBuffers() { |
698 DCHECK_EQ(base::TimeTicks(), swap_start_time_); | 740 DCHECK_EQ(base::TimeTicks(), swap_start_time_); |
699 swap_start_time_ = Now(); | 741 swap_start_time_ = Now(); |
742 swap_ack_watchdog_enabled_ = true; | |
743 swap_ack_watchdog_begin_impl_frame_count_ = 0; | |
700 } | 744 } |
701 | 745 |
702 void CompositorTimingHistory::DidSwapBuffersComplete() { | 746 void CompositorTimingHistory::DidSwapBuffersComplete() { |
703 DCHECK_NE(base::TimeTicks(), swap_start_time_); | 747 DCHECK_NE(base::TimeTicks(), swap_start_time_); |
704 base::TimeDelta swap_to_ack_duration = Now() - swap_start_time_; | 748 base::TimeDelta swap_to_ack_duration = Now() - swap_start_time_; |
705 uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration); | 749 uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration); |
750 if (swap_ack_watchdog_enabled_) { | |
751 uma_reporter_->AddSwapAckWasFast(true); | |
752 swap_ack_watchdog_enabled_ = false; | |
753 } | |
706 swap_start_time_ = base::TimeTicks(); | 754 swap_start_time_ = base::TimeTicks(); |
707 } | 755 } |
708 | 756 |
709 } // namespace cc | 757 } // namespace cc |
OLD | NEW |