| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 const size_t kDurationHistorySize = 60; | 51 const size_t kDurationHistorySize = 60; |
| 52 const double kBeginMainFrameQueueDurationEstimationPercentile = 90.0; | 52 const double kBeginMainFrameQueueDurationEstimationPercentile = 90.0; |
| 53 const double kBeginMainFrameQueueDurationCriticalEstimationPercentile = 90.0; | 53 const double kBeginMainFrameQueueDurationCriticalEstimationPercentile = 90.0; |
| 54 const double kBeginMainFrameQueueDurationNotCriticalEstimationPercentile = 90.0; | 54 const double kBeginMainFrameQueueDurationNotCriticalEstimationPercentile = 90.0; |
| 55 const double kBeginMainFrameStartToCommitEstimationPercentile = 90.0; | 55 const double kBeginMainFrameStartToCommitEstimationPercentile = 90.0; |
| 56 const double kCommitToReadyToActivateEstimationPercentile = 90.0; | 56 const double kCommitToReadyToActivateEstimationPercentile = 90.0; |
| 57 const double kPrepareTilesEstimationPercentile = 90.0; | 57 const double kPrepareTilesEstimationPercentile = 90.0; |
| 58 const double kActivateEstimationPercentile = 90.0; | 58 const double kActivateEstimationPercentile = 90.0; |
| 59 const double kDrawEstimationPercentile = 90.0; | 59 const double kDrawEstimationPercentile = 90.0; |
| 60 | 60 |
| 61 // The watchdog uses a combination of BeginImplFrame counts and |
| 62 // actual timestamps to avoid calling Now() too often or adding |
| 63 // unnecessary idle wakeups. |
| 64 // This will break if we aren't receiving BeginFrames, but this |
| 65 // is primarily for crbug.com/602486, where we are receiving them. |
| 66 const int kSwapAckWatchdogBeginImplFrameCount = 8 * 61; |
| 67 const int kSwapAckWatchdogBeginImplFrameReCount = 60; |
| 68 const base::TimeDelta kSwapAckWatchdogTimeout = |
| 69 base::TimeDelta::FromMicroseconds(8000000); |
| 70 |
| 61 const int kUmaDurationMinMicros = 1; | 71 const int kUmaDurationMinMicros = 1; |
| 62 const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5; | 72 const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5; |
| 63 const int kUmaDurationBucketCount = 100; | 73 const int kUmaDurationBucketCount = 100; |
| 64 | 74 |
| 65 // This macro is deprecated since its bucket count uses too much bandwidth. | 75 // This macro is deprecated since its bucket count uses too much bandwidth. |
| 66 // It also has sub-optimal range and bucket distribution. | 76 // It also has sub-optimal range and bucket distribution. |
| 67 // TODO(brianderson): Delete this macro and associated UMAs once there is | 77 // TODO(brianderson): Delete this macro and associated UMAs once there is |
| 68 // sufficient overlap with the re-bucketed UMAs. | 78 // sufficient overlap with the re-bucketed UMAs. |
| 69 #define UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample) \ | 79 #define UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample) \ |
| 70 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample.InMicroseconds(), \ | 80 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample.InMicroseconds(), \ |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 void AddActivateDuration(base::TimeDelta duration) override {} | 299 void AddActivateDuration(base::TimeDelta duration) override {} |
| 290 void AddDrawDuration(base::TimeDelta duration) override {} | 300 void AddDrawDuration(base::TimeDelta duration) override {} |
| 291 void AddSwapToAckLatency(base::TimeDelta duration) override {} | 301 void AddSwapToAckLatency(base::TimeDelta duration) override {} |
| 292 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} | 302 void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} |
| 293 }; | 303 }; |
| 294 | 304 |
| 295 } // namespace | 305 } // namespace |
| 296 | 306 |
| 297 CompositorTimingHistory::CompositorTimingHistory( | 307 CompositorTimingHistory::CompositorTimingHistory( |
| 298 bool using_synchronous_renderer_compositor, | 308 bool using_synchronous_renderer_compositor, |
| 309 bool enable_swap_ack_watchdog, |
| 299 UMACategory uma_category, | 310 UMACategory uma_category, |
| 300 RenderingStatsInstrumentation* rendering_stats_instrumentation) | 311 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
| 301 : using_synchronous_renderer_compositor_( | 312 : using_synchronous_renderer_compositor_( |
| 302 using_synchronous_renderer_compositor), | 313 using_synchronous_renderer_compositor), |
| 303 enabled_(false), | 314 enabled_(false), |
| 304 did_send_begin_main_frame_(false), | 315 did_send_begin_main_frame_(false), |
| 305 begin_main_frame_needed_continuously_(false), | 316 begin_main_frame_needed_continuously_(false), |
| 306 begin_main_frame_committing_continuously_(false), | 317 begin_main_frame_committing_continuously_(false), |
| 307 compositor_drawing_continuously_(false), | 318 compositor_drawing_continuously_(false), |
| 308 begin_main_frame_queue_duration_history_(kDurationHistorySize), | 319 begin_main_frame_queue_duration_history_(kDurationHistorySize), |
| 309 begin_main_frame_queue_duration_critical_history_(kDurationHistorySize), | 320 begin_main_frame_queue_duration_critical_history_(kDurationHistorySize), |
| 310 begin_main_frame_queue_duration_not_critical_history_( | 321 begin_main_frame_queue_duration_not_critical_history_( |
| 311 kDurationHistorySize), | 322 kDurationHistorySize), |
| 312 begin_main_frame_start_to_commit_duration_history_(kDurationHistorySize), | 323 begin_main_frame_start_to_commit_duration_history_(kDurationHistorySize), |
| 313 commit_to_ready_to_activate_duration_history_(kDurationHistorySize), | 324 commit_to_ready_to_activate_duration_history_(kDurationHistorySize), |
| 314 prepare_tiles_duration_history_(kDurationHistorySize), | 325 prepare_tiles_duration_history_(kDurationHistorySize), |
| 315 activate_duration_history_(kDurationHistorySize), | 326 activate_duration_history_(kDurationHistorySize), |
| 316 draw_duration_history_(kDurationHistorySize), | 327 draw_duration_history_(kDurationHistorySize), |
| 317 begin_main_frame_on_critical_path_(false), | 328 begin_main_frame_on_critical_path_(false), |
| 329 swap_ack_watchdog_enabled_(enable_swap_ack_watchdog), |
| 330 swap_ack_watchdog_begin_impl_frame_count_(0), |
| 318 uma_reporter_(CreateUMAReporter(uma_category)), | 331 uma_reporter_(CreateUMAReporter(uma_category)), |
| 319 rendering_stats_instrumentation_(rendering_stats_instrumentation) {} | 332 rendering_stats_instrumentation_(rendering_stats_instrumentation) {} |
| 320 | 333 |
| 321 CompositorTimingHistory::~CompositorTimingHistory() { | 334 CompositorTimingHistory::~CompositorTimingHistory() { |
| 322 } | 335 } |
| 323 | 336 |
| 324 std::unique_ptr<CompositorTimingHistory::UMAReporter> | 337 std::unique_ptr<CompositorTimingHistory::UMAReporter> |
| 325 CompositorTimingHistory::CreateUMAReporter(UMACategory category) { | 338 CompositorTimingHistory::CreateUMAReporter(UMACategory category) { |
| 326 switch (category) { | 339 switch (category) { |
| 327 case RENDERER_UMA: | 340 case RENDERER_UMA: |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 } | 449 } |
| 437 | 450 |
| 438 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { | 451 base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { |
| 439 return draw_duration_history_.Percentile(kDrawEstimationPercentile); | 452 return draw_duration_history_.Percentile(kDrawEstimationPercentile); |
| 440 } | 453 } |
| 441 | 454 |
| 442 void CompositorTimingHistory::DidCreateAndInitializeOutputSurface() { | 455 void CompositorTimingHistory::DidCreateAndInitializeOutputSurface() { |
| 443 // After we get a new output surface, we won't get a spurious | 456 // After we get a new output surface, we won't get a spurious |
| 444 // swap ack from the old output surface. | 457 // swap ack from the old output surface. |
| 445 swap_start_time_ = base::TimeTicks(); | 458 swap_start_time_ = base::TimeTicks(); |
| 459 swap_ack_watchdog_begin_impl_frame_count_ = 0; |
| 446 } | 460 } |
| 447 | 461 |
| 448 void CompositorTimingHistory::WillBeginImplFrame( | 462 void CompositorTimingHistory::WillBeginImplFrame( |
| 449 bool new_active_tree_is_likely) { | 463 bool new_active_tree_is_likely) { |
| 450 // The check for whether a BeginMainFrame was sent anytime between two | 464 // The check for whether a BeginMainFrame was sent anytime between two |
| 451 // BeginImplFrames protects us from not detecting a fast main thread that | 465 // BeginImplFrames protects us from not detecting a fast main thread that |
| 452 // does all it's work and goes idle in between BeginImplFrames. | 466 // does all it's work and goes idle in between BeginImplFrames. |
| 453 // For example, this may happen if an animation is being driven with | 467 // 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 | 468 // setInterval(17) or if input events just happen to arrive in the |
| 455 // middle of every frame. | 469 // middle of every frame. |
| 456 if (!new_active_tree_is_likely && !did_send_begin_main_frame_) { | 470 if (!new_active_tree_is_likely && !did_send_begin_main_frame_) { |
| 457 SetBeginMainFrameNeededContinuously(false); | 471 SetBeginMainFrameNeededContinuously(false); |
| 458 SetBeginMainFrameCommittingContinuously(false); | 472 SetBeginMainFrameCommittingContinuously(false); |
| 459 } | 473 } |
| 460 | 474 |
| 475 // After N BeginImplFrames, check if the swap ack is taking too long. |
| 476 // If it is, crash to get diagnostic information. |
| 477 // Otherwise, check again in M BeginImplFrames. |
| 478 if (swap_ack_watchdog_enabled_ && !swap_start_time_.is_null()) { |
| 479 swap_ack_watchdog_begin_impl_frame_count_++; |
| 480 if (swap_ack_watchdog_begin_impl_frame_count_ == |
| 481 kSwapAckWatchdogBeginImplFrameCount) { |
| 482 base::TimeDelta swap_not_acked_time_ = Now() - swap_start_time_; |
| 483 CHECK_LT(swap_not_acked_time_, kSwapAckWatchdogTimeout); |
| 484 swap_ack_watchdog_begin_impl_frame_count_ -= |
| 485 kSwapAckWatchdogBeginImplFrameReCount; |
| 486 } |
| 487 } |
| 488 |
| 461 did_send_begin_main_frame_ = false; | 489 did_send_begin_main_frame_ = false; |
| 462 } | 490 } |
| 463 | 491 |
| 464 void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw) { | 492 void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw) { |
| 465 if (!needs_redraw) | 493 if (!needs_redraw) |
| 466 SetCompositorDrawingContinuously(false); | 494 SetCompositorDrawingContinuously(false); |
| 467 } | 495 } |
| 468 | 496 |
| 469 void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() { | 497 void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() { |
| 470 SetBeginMainFrameNeededContinuously(false); | 498 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; | 718 new_active_tree_draw_end_time_prev_ = draw_end_time; |
| 691 } | 719 } |
| 692 } | 720 } |
| 693 | 721 |
| 694 draw_start_time_ = base::TimeTicks(); | 722 draw_start_time_ = base::TimeTicks(); |
| 695 } | 723 } |
| 696 | 724 |
| 697 void CompositorTimingHistory::DidSwapBuffers() { | 725 void CompositorTimingHistory::DidSwapBuffers() { |
| 698 DCHECK_EQ(base::TimeTicks(), swap_start_time_); | 726 DCHECK_EQ(base::TimeTicks(), swap_start_time_); |
| 699 swap_start_time_ = Now(); | 727 swap_start_time_ = Now(); |
| 728 swap_ack_watchdog_begin_impl_frame_count_ = 0; |
| 700 } | 729 } |
| 701 | 730 |
| 702 void CompositorTimingHistory::DidSwapBuffersComplete() { | 731 void CompositorTimingHistory::DidSwapBuffersComplete() { |
| 703 DCHECK_NE(base::TimeTicks(), swap_start_time_); | 732 DCHECK_NE(base::TimeTicks(), swap_start_time_); |
| 704 base::TimeDelta swap_to_ack_duration = Now() - swap_start_time_; | 733 base::TimeDelta swap_to_ack_duration = Now() - swap_start_time_; |
| 705 uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration); | 734 uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration); |
| 706 swap_start_time_ = base::TimeTicks(); | 735 swap_start_time_ = base::TimeTicks(); |
| 707 } | 736 } |
| 708 | 737 |
| 709 } // namespace cc | 738 } // namespace cc |
| OLD | NEW |