Bug 1349808 - Add telemetry for cases when we can't run async animations due to layer size being too large. data-review=bsmedberg, r=birtles,botond
MozReview-Commit-ID: 61DBw1DHbQA
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -124,16 +124,21 @@ KeyframeEffect::SetTarget(const Nullable
nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc());
if (mAnimation) {
nsNodeUtils::AnimationAdded(mAnimation);
}
} else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
// New target is null, so fall back to distribute spacing.
KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
}
+
+ // If the new target frame is also oversized we should probably record that
+ // too so we have a more complete picture of the type of frame sizes we
+ // encounter, hence we reset the telemetry flag here.
+ mRecordedContentTooLarge = false;
}
void
KeyframeEffect::SetIterationComposite(
const IterationCompositeOperation& aIterationComposite,
CallerType aCallerType)
{
// Ignore iterationComposite if the Web Animations API is not enabled,
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -1,28 +1,30 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/dom/KeyframeEffectReadOnly.h"
+#include "gfxPrefs.h"
#include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
// For UnrestrictedDoubleOrKeyframeAnimationOptions;
#include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/AnimValuesStyleRule.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/EffectSet.h"
#include "mozilla/FloatingPoint.h" // For IsFinite
#include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt
#include "mozilla/KeyframeUtils.h"
#include "mozilla/ServoBindings.h"
+#include "mozilla/Telemetry.h"
#include "mozilla/TypeTraits.h"
#include "Layers.h" // For Layer
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContextForElement
#include "nsContentUtils.h" // nsContentUtils::ReportToConsole
#include "nsCSSPropertyIDSet.h"
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
#include "nsCSSPseudoElements.h" // For CSSPseudoElementType
#include "nsIPresShell.h"
@@ -1592,16 +1594,41 @@ KeyframeEffectReadOnly::HasGeometricProp
return false;
}
void
KeyframeEffectReadOnly::SetPerformanceWarning(
nsCSSPropertyID aProperty,
const AnimationPerformanceWarning& aWarning)
{
+ if (aWarning.mType == AnimationPerformanceWarning::Type::ContentTooLarge &&
+ !mRecordedContentTooLarge) {
+ // ContentTooLarge stores: frameSize (w x h),
+ // relativeLimit (w x h), i.e. =~ viewport size *
+ // ratioLimit
+ // absoluteLimit (w x h)
+ MOZ_ASSERT(aWarning.mParams && aWarning.mParams->Length() >= 4,
+ "ContentTooLarge warning should have at least 4 parameters");
+ const nsTArray<int32_t>& params = aWarning.mParams.ref();
+ uint32_t frameSize = uint32_t(params[0]) * params[1];
+ float viewportRatioX = gfxPrefs::AnimationPrerenderViewportRatioLimitX();
+ float viewportRatioY = gfxPrefs::AnimationPrerenderViewportRatioLimitY();
+ double viewportWidth = viewportRatioX ? params[2] / viewportRatioX
+ : params[2];
+ double viewportHeight = viewportRatioY ? params[3] / viewportRatioY
+ : params[3];
+ double viewportSize = viewportWidth * viewportHeight;
+ uint32_t frameToViewport = frameSize / viewportSize * 100.0;
+ Telemetry::Accumulate(
+ Telemetry::ASYNC_ANIMATION_CONTENT_TOO_LARGE_FRAME_SIZE, frameSize);
+ Telemetry::Accumulate(
+ Telemetry::ASYNC_ANIMATION_CONTENT_TOO_LARGE_PERCENTAGE, frameToViewport);
+ mRecordedContentTooLarge = true;
+ }
+
for (AnimationProperty& property : mProperties) {
if (property.mProperty == aProperty &&
(!property.mPerformanceWarning ||
*property.mPerformanceWarning != aWarning)) {
property.mPerformanceWarning = Some(aWarning);
nsXPIDLString localizedString;
if (nsLayoutUtils::IsAnimationLoggingEnabled() &&
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -450,16 +450,21 @@ protected:
// we need to re-evaluate the cascade of animations when that changes.
bool mInEffectOnLastAnimationTimingUpdate;
// The non-animated values for properties in this effect that contain at
// least one animation value that is composited with the underlying value
// (i.e. it uses the additive or accumulate composite mode).
nsDataHashtable<nsUint32HashKey, StyleAnimationValue> mBaseStyleValues;
+ // We only want to record telemetry data for "ContentTooLarge" warnings once
+ // per effect:target pair so we use this member to record if we have already
+ // reported a "ContentTooLarge" warning for the current target.
+ bool mRecordedContentTooLarge = false;
+
private:
nsChangeHint mCumulativeChangeHint;
template<typename StyleType>
void DoSetKeyframes(nsTArray<Keyframe>&& aKeyframes, StyleType&& aStyle);
template<typename StyleType>
void DoUpdateProperties(StyleType&& aStyle);
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -132,16 +132,35 @@
"APPLICATION_REPUTATION_ALLOWLIST_MATCH": {
"alert_emails": ["safebrowsing-telemetry@mozilla.org"],
"expires_in_version": "60",
"kind": "enumerated",
"n_values": 4,
"bug_numbers": [1331139],
"description": "For each Application Reputation lookup against both the V2 and V4 Google lists, note which version of the allow list returned a match (0 = no match, 1 = match only V2, 2 = match only V4, 3 = match both V2 and V4)"
},
+ "ASYNC_ANIMATION_CONTENT_TOO_LARGE_FRAME_SIZE": {
+ "alert_emails": ["bbirtles@mozilla.com"],
+ "expires_in_version": "59",
+ "kind": "exponential",
+ "high": 80000000,
+ "n_buckets": 100,
+ "bug_numbers": [1100357, 1349808],
+ "description": "The number of pixels of the frame for each time we encountered a layer that was so large we decided not to run its animations on the compositor."
+ },
+ "ASYNC_ANIMATION_CONTENT_TOO_LARGE_PERCENTAGE": {
+ "alert_emails": ["bbirtles@mozilla.com"],
+ "expires_in_version": "59",
+ "kind": "exponential",
+ "low": 100,
+ "high": 1000,
+ "n_buckets": 50,
+ "bug_numbers": [1100357, 1349808],
+ "description": "The ratio of the frame size (in total number of pixels) to the relative limit (~viewport size plus some tolerance factor, typically 12.5% in each dimension, i.e. ~27% tolerance in total area) for each time we encountered a layer that was so large we decided not to run its animations on the compositor expressed as a percentage (e.g. 130 = frame area was 30% larger than the relative limit)"
+ },
"AUDIOSTREAM_FIRST_OPEN_MS": {
"expires_in_version": "50",
"kind": "exponential",
"high": 10000,
"n_buckets": 50,
"description": "The length of time (in milliseconds) for the first open of AudioStream."
},
"AUDIOSTREAM_LATER_OPEN_MS": {