Chromium Code Reviews| 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 |