Bug 1339220 - Add telemetry probes to measure duration and max-area of animations in the compositor. r=botond,bsmedberg
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 16 Feb 2017 14:40:37 -0500
changeset 490508 8ddcd324a0f15735586d9b33dbad87ef4603de89
parent 490507 1890ccdab48d10d4dc6532b97fcdd743d25c635b
child 490509 6c1627e917136d72f3b7d74da2d10d45315dd929
push id47118
push userbmo:ttromey@mozilla.com
push dateTue, 28 Feb 2017 17:09:36 +0000
reviewersbotond, bsmedberg
bugs1339220
milestone54.0a1
Bug 1339220 - Add telemetry probes to measure duration and max-area of animations in the compositor. r=botond,bsmedberg MozReview-Commit-ID: KyvsNSTcxG8
gfx/layers/composite/AnimationMetricsTracker.cpp
gfx/layers/composite/AnimationMetricsTracker.h
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
gfx/layers/moz.build
toolkit/components/telemetry/Histograms.json
new file mode 100644
--- /dev/null
+++ b/gfx/layers/composite/AnimationMetricsTracker.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/AnimationMetricsTracker.h"
+
+#include <algorithm>
+#include <inttypes.h>
+#include "mozilla/Telemetry.h"
+
+#define AMT_LOG(...)
+// #define AMT_LOG(...) printf_stderr("AMT: " __VA_ARGS__)
+
+namespace mozilla {
+namespace layers {
+
+AnimationMetricsTracker::AnimationMetricsTracker()
+{
+}
+
+AnimationMetricsTracker::~AnimationMetricsTracker()
+{
+}
+
+void
+AnimationMetricsTracker::UpdateAnimationInProgress(bool aInProgress,
+                                                   uint64_t aLayerArea)
+{
+  MOZ_ASSERT(aInProgress || aLayerArea == 0);
+  if (mCurrentAnimationStart && !aInProgress) {
+    AnimationEnded();
+    mCurrentAnimationStart = TimeStamp();
+    mMaxLayerAreaAnimated = 0;
+  } else if (aInProgress) {
+    if (!mCurrentAnimationStart) {
+      mCurrentAnimationStart = TimeStamp::Now();
+      mMaxLayerAreaAnimated = aLayerArea;
+      AnimationStarted();
+    } else {
+      mMaxLayerAreaAnimated = std::max(mMaxLayerAreaAnimated, aLayerArea);
+    }
+  }
+}
+
+void
+AnimationMetricsTracker::AnimationStarted()
+{
+}
+
+void
+AnimationMetricsTracker::AnimationEnded()
+{
+  MOZ_ASSERT(mCurrentAnimationStart);
+  Telemetry::AccumulateTimeDelta(Telemetry::COMPOSITOR_ANIMATION_DURATION, mCurrentAnimationStart);
+  Telemetry::Accumulate(Telemetry::COMPOSITOR_ANIMATION_MAX_LAYER_AREA, mMaxLayerAreaAnimated);
+  AMT_LOG("Ended animation; duration: %f ms, area: %" PRIu64 "\n",
+    (TimeStamp::Now() - mCurrentAnimationStart).ToMilliseconds(),
+    mMaxLayerAreaAnimated);
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/composite/AnimationMetricsTracker.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_AnimationMetricsTracker_h
+#define mozilla_layers_AnimationMetricsTracker_h
+
+#include "mozilla/TimeStamp.h"
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * Tracks the start and end of compositor animations.
+ */
+class AnimationMetricsTracker {
+public:
+  AnimationMetricsTracker();
+  ~AnimationMetricsTracker();
+
+  /**
+   * This function should be called per composite, to inform the metrics
+   * tracker if any animation is in progress, and if so, what area is
+   * being animated. The aLayerArea is in Layer pixels squared.
+   */
+  void UpdateAnimationInProgress(bool aInProgress, uint64_t aLayerArea);
+
+private:
+  void AnimationStarted();
+  void AnimationEnded();
+
+  TimeStamp mCurrentAnimationStart;
+  uint64_t mMaxLayerAreaAnimated;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_AnimationMetricsTracker_h
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -629,38 +629,41 @@ ApplyAnimatedValue(Layer* aLayer,
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
   }
 }
 
 static bool
-SampleAnimations(Layer* aLayer, TimeStamp aPoint)
+SampleAnimations(Layer* aLayer, TimeStamp aPoint, uint64_t* aLayerAreaAnimated)
 {
   bool activeAnimations = false;
 
   ForEachNode<ForwardIterator>(
       aLayer,
-      [&activeAnimations, &aPoint] (Layer* layer)
+      [&activeAnimations, &aPoint, &aLayerAreaAnimated] (Layer* layer)
       {
         bool hasInEffectAnimations = false;
         StyleAnimationValue animationValue = layer->GetBaseAnimationStyle();
         activeAnimations |=
           AnimationHelper::SampleAnimationForEachNode(aPoint,
                                                       layer->GetAnimations(),
                                                       layer->GetAnimationData(),
                                                       animationValue,
                                                       hasInEffectAnimations);
         if (hasInEffectAnimations) {
           Animation& animation = layer->GetAnimations().LastElement();
           ApplyAnimatedValue(layer,
                              animation.property(),
                              animation.data(),
                              animationValue);
+          if (aLayerAreaAnimated) {
+            *aLayerAreaAnimated += (layer->GetVisibleRegion().Area());
+          }
         }
       });
   return activeAnimations;
 }
 
 static bool
 SampleAPZAnimations(const LayerMetricsWrapper& aLayer, TimeStamp aSampleTime)
 {
@@ -1306,19 +1309,23 @@ AsyncCompositionManager::TransformShadow
 
   // First, compute and set the shadow transforms from OMT animations.
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
   // Use a previous vsync time to make main thread animations and compositor
   // more in sync with each other.
   // On the initial frame we use aVsyncTimestamp here so the timestamp on the
   // second frame are the same as the initial frame, but it does not matter.
+  uint64_t layerAreaAnimated = 0;
   bool wantNextFrame = SampleAnimations(root,
     !mPreviousFrameTimeStamp.IsNull() ?
-      mPreviousFrameTimeStamp : aCurrentFrame);
+      mPreviousFrameTimeStamp : aCurrentFrame,
+    &layerAreaAnimated);
+  mAnimationMetricsTracker.UpdateAnimationInProgress(
+    wantNextFrame, layerAreaAnimated);
 
   // Reset the previous time stamp if we don't already have any running
   // animations to avoid using the time which is far behind for newly
   // started animations.
   mPreviousFrameTimeStamp = wantNextFrame ? aCurrentFrame : TimeStamp();
 
   if (!(aSkip & TransformsToSkip::APZ)) {
     // FIXME/bug 775437: unify this interface with the ~native-fennec
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -9,16 +9,17 @@
 #include "Units.h"                      // for ScreenPoint, etc
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerManagerComposite
 #include "mozilla/Attributes.h"         // for final, etc
 #include "mozilla/RefPtr.h"             // for RefCounted
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
+#include "mozilla/layers/AnimationMetricsTracker.h" // for AnimationMetricsTracker
 #include "mozilla/layers/FrameUniformityData.h" // For FrameUniformityData
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "mozilla/RefPtr.h"                   // for nsRefPtr
 #include "nsISupportsImpl.h"            // for LayerManager::AddRef, etc
 
 namespace mozilla {
 namespace layers {
 
@@ -233,16 +234,17 @@ private:
   int32_t mPaintSyncId;
 
   bool mReadyForCompose;
 
   gfx::Matrix mWorldTransform;
   LayerTransformRecorder mLayerTransformRecorder;
 
   TimeStamp mPreviousFrameTimeStamp;
+  AnimationMetricsTracker mAnimationMetricsTracker;
 
 #ifdef MOZ_WIDGET_ANDROID
   // The following two fields are only needed on Fennec with C++ APZ, because
   // then we need to reposition the gecko scrollbar to deal with the
   // dynamic toolbar shifting content around.
   FrameMetrics::ViewID mRootScrollableId;
   ScreenMargin mFixedLayerMargins;
 #endif
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -137,16 +137,17 @@ EXPORTS.mozilla.layers += [
     'client/GPUVideoTextureClient.h',
     'client/ImageClient.h',
     'client/SingleTiledContentClient.h',
     'client/TextureClient.h',
     'client/TextureClientPool.h',
     'client/TextureClientRecycleAllocator.h',
     'client/TextureClientSharedSurface.h',
     'client/TiledContentClient.h',
+    'composite/AnimationMetricsTracker.h',
     'composite/AsyncCompositionManager.h',
     'composite/CanvasLayerComposite.h',
     'composite/ColorLayerComposite.h',
     'composite/ContainerLayerComposite.h',
     'composite/ContentHost.h',
     'composite/FrameUniformityData.h',
     'composite/GPUVideoTextureHost.h',
     'composite/ImageComposite.h',
@@ -317,16 +318,17 @@ UNIFIED_SOURCES += [
     'client/GPUVideoTextureClient.cpp',
     'client/ImageClient.cpp',
     'client/SingleTiledContentClient.cpp',
     'client/TextureClient.cpp',
     'client/TextureClientPool.cpp',
     'client/TextureClientRecycleAllocator.cpp',
     'client/TextureClientSharedSurface.cpp',
     'client/TiledContentClient.cpp',
+    'composite/AnimationMetricsTracker.cpp',
     'composite/AsyncCompositionManager.cpp',
     'composite/CanvasLayerComposite.cpp',
     'composite/ColorLayerComposite.cpp',
     'composite/CompositableHost.cpp',
     'composite/ContainerLayerComposite.cpp',
     'composite/ContentHost.cpp',
     'composite/FPSCounter.cpp',
     'composite/FrameUniformityData.cpp',
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -252,16 +252,34 @@
   },
   "COMPOSITE_FRAME_ROUNDTRIP_TIME" : {
     "expires_in_version": "never",
     "description": "Time from vsync to finishing a composite in milliseconds.",
     "kind": "exponential",
     "high": 1000,
     "n_buckets": 50
   },
+  "COMPOSITOR_ANIMATION_DURATION" : {
+    "expires_in_version": "58",
+    "description": "Duration of animations running on the compositor in milliseconds",
+    "kind": "exponential",
+    "high": 20000,
+    "n_buckets": 50,
+    "alert_emails": ["kgupta@mozilla.com"],
+    "bug_numbers": [1339220]
+  },
+  "COMPOSITOR_ANIMATION_MAX_LAYER_AREA" : {
+    "expires_in_version": "58",
+    "description": "High-watermark of layer area affected during a compositor animation. Units are layer pixels squared.",
+    "kind": "exponential",
+    "high": 8294400,
+    "n_buckets": 50,
+    "alert_emails": ["kgupta@mozilla.com"],
+    "bug_numbers": [1339220]
+  },
   "CONTENT_PROCESS_LAUNCH_TIME_MS" : {
     "alert_emails": ["bsmedberg@mozilla.com", "mconley@mozilla.com"],
     "expires_in_version": "57",
     "bug_numbers": [1304790],
     "kind": "exponential",
     "high": 64000,
     "n_buckets": 100,
     "releaseChannelCollection": "opt-out",