Bug 800031. Include paint time int tab switch telemetry. r=ehsan,dao,bjcaob
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 11 Oct 2012 13:54:27 -0400
changeset 110105 155f7491ad68b9c615ebadb39e3ab0bfb2f0ebff
parent 110104 651bd0042def36d5b541cfc48c96f7bbb9dbe5ee
child 110106 4c134de65570d795fd7b9594d538b7494bdc0082
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersehsan, dao, bjcaob
bugs800031
milestone19.0a1
Bug 800031. Include paint time int tab switch telemetry. r=ehsan,dao,bjcaob This adds a new FX_TAB_SWITCH_TOTAL_MS that should more accurately represent the user experience of tab switch time than FX_TAB_SWITCH_UPDATE_MS. FX_TAB_SWITCH_UPDATE_MS is being kept because it gives a good indication of how much time is being spent in the front end parts vs the painting parts. This works by measuring the time between beginTabSwitch() and the first call to LayerManager::PostPresent().
browser/base/content/tabbrowser.xml
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicLayerManager.cpp
toolkit/components/telemetry/Histograms.json
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -831,18 +831,21 @@
       <method name="updateCurrentBrowser">
         <parameter name="aForceUpdate"/>
         <body>
           <![CDATA[
             var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
             if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
               return;
 
-            if (!aForceUpdate)
+            if (!aForceUpdate) {
               TelemetryStopwatch.start("FX_TAB_SWITCH_UPDATE_MS");
+              window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
+                                                             .beginTabSwitch();
+            }
 
             var oldTab = this.mCurrentTab;
 
             // Preview mode should not reset the owner
             if (!this._previewMode && oldTab != this.selectedTab)
               oldTab.owner = null;
 
             if (this._lastRelatedTab) {
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2127,16 +2127,36 @@ nsDOMWindowUtils::StopFrameTimeRecording
     for (uint32_t i = 0; i < *frameCount; i++) {
       (*frames)[i] = frameTimes[i];
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::BeginTabSwitch()
+{
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
+  LayerManager *mgr = widget->GetLayerManager();
+  if (!mgr)
+    return NS_ERROR_FAILURE;
+
+  mgr->BeginTabSwitch();
+
+  return NS_OK;
+}
+
 static bool
 ComputeAnimationValue(nsCSSProperty aProperty,
                       Element* aElement,
                       const nsAString& aInput,
                       nsStyleAnimation::Value& aOutput)
 {
 
   if (!nsStyleAnimation::ComputeValue(aProperty, aElement, aInput,
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -35,17 +35,17 @@ interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 
-[scriptable, uuid(a76927b7-4aca-4cd1-9c2b-a6b4789b88c3)]
+[scriptable, uuid(12167eee-ff9c-4c8e-a89d-b097b1825089)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1046,16 +1046,22 @@ interface nsIDOMWindowUtils : nsISupport
    * error if there is no widget associated with this window.
    */
   readonly attribute AString layerManagerType;
 
   void startFrameTimeRecording();
   void stopFrameTimeRecording([optional] out unsigned long frameCount,
                               [retval, array, size_is(frameCount)] out float frameTime);
   /**
+   * Signals that we're begining to tab switch. This is used by painting code to
+   * determine total tab switch time.
+   */
+  void beginTabSwitch();
+
+  /**
    * The DPI of the display
    */
   readonly attribute float displayDPI;
 
   /**
    * Return the outer window with the given ID, if any.  Can return null.
    */
   nsIDOMWindow getOuterWindowWithId(in unsigned long long aOuterWindowID);
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2,16 +2,17 @@
  * vim: sw=2 ts=8 et :
  */
 /* 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/PLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
+#include "mozilla/Telemetry.h"
 
 #include "ImageLayers.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
 #include "ReadbackLayer.h"
 #include "gfxUtils.h"
 #include "nsPrintfCString.h"
@@ -871,28 +872,37 @@ LayerManager::StartFrameTimeRecording()
 void
 LayerManager::PostPresent()
 {
   if (!mLastFrameTime.IsNull()) {
     TimeStamp now = TimeStamp::Now();
     mFrameTimes.AppendElement((now - mLastFrameTime).ToMilliseconds());
     mLastFrameTime = now;
   }
+  if (!mTabSwitchStart.IsNull()) {
+    Telemetry::Accumulate(Telemetry::FX_TAB_SWITCH_TOTAL_MS,
+                          uint32_t((TimeStamp::Now() - mTabSwitchStart).ToMilliseconds()));
+    mTabSwitchStart = TimeStamp();
+  }
 }
 
 nsTArray<float>
 LayerManager::StopFrameTimeRecording()
 {
   mLastFrameTime = TimeStamp();
   nsTArray<float> result = mFrameTimes;
   mFrameTimes.Clear();
   return result;
 }
 
-
+void
+LayerManager::BeginTabSwitch()
+{
+  mTabSwitchStart = TimeStamp::Now();
+}
 
 #ifdef MOZ_LAYERS_HAVE_LOG
 
 static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
 
 #ifdef MOZ_DUMP_PAINTING
 template <typename T>
 void WriteSnapshotLinkToDumpFile(T* aObj, FILE* aFile)
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -463,16 +463,18 @@ public:
    */
   void LogSelf(const char* aPrefix="");
 
   void StartFrameTimeRecording();
   nsTArray<float> StopFrameTimeRecording();
 
   void PostPresent();
 
+  void BeginTabSwitch();
+
   static bool IsLogEnabled();
   static PRLogModuleInfo* GetLog() { return sLog; }
 
   bool IsCompositingCheap(LayersBackend aBackend)
   { return LAYERS_BASIC != aBackend; }
 
   virtual bool IsCompositingCheap() { return true; }
 
@@ -490,16 +492,17 @@ protected:
 
   static void InitLog();
   static PRLogModuleInfo* sLog;
   uint64_t mId;
   bool mInTransaction;
 private:
   TimeStamp mLastFrameTime;
   nsTArray<float> mFrameTimes;
+  TimeStamp mTabSwitchStart;
 };
 
 class ThebesLayer;
 typedef InfallibleTArray<Animation> AnimationArray;
 
 struct AnimData {
   InfallibleTArray<nsStyleAnimation::Value> mStartValues;
   InfallibleTArray<nsStyleAnimation::Value> mEndValues;
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -585,16 +585,17 @@ BasicLayerManager::EndTransactionInterna
         PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
       }
       // If we're not retained, then don't composite means do nothing at all.
     } else {
       PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
       if (mWidget) {
         FlashWidgetUpdateArea(mTarget);
       }
+      LayerManager::PostPresent();
     }
 
     if (!mTransactionIncomplete) {
       // Clear out target if we have a complete transaction.
       mTarget = nullptr;
     }
   }
 
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1922,16 +1922,22 @@
     "description": "Firefox: Time taken by the tab closing animation in milliseconds"
   },
   "FX_TAB_SWITCH_UPDATE_MS": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 20,
     "description": "Firefox: Time in ms spent updating UI in response to a tab switch"
   },
+  "FX_TAB_SWITCH_TOTAL_MS": {
+    "kind": "exponential",
+    "high": "1000",
+    "n_buckets": 20,
+    "description": "Firefox: Time in ms till a tab switch is complete including the first paint"
+  },
   "FX_KEYWORD_URL_USERSET": {
     "kind": "boolean",
     "description": "Firefox: keyword.URL has a user-set value"
   },
   "FX_IDENTITY_POPUP_OPEN_MS": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 10,