Bug 1474253 - Improve ReportPerformanceInfo() draft
authorTarek Ziadé <tarek@mozilla.com>
Mon, 09 Jul 2018 16:07:15 +0200
changeset 815606 983d3cda182ff4a20f71e702c111f10c03e27d89
parent 815592 3d20b0701781731e0f9b08e1cd40ac842f385e03
push id115571
push usertziade@mozilla.com
push dateMon, 09 Jul 2018 14:08:18 +0000
bugs1474253
milestone63.0a1
Bug 1474253 - Improve ReportPerformanceInfo() - modifies how we get the top window id, add isTopLevel - rename pwid to windowId, worker to isWorker - removes the wid field It also fixes PerformanceInfoDictionary.host type MozReview-Commit-ID: 4AzO3UnJ2LM
dom/base/DocGroup.cpp
dom/chrome-webidl/ChromeUtils.webidl
dom/ipc/DOMTypes.ipdlh
dom/tests/browser/browser_test_performance_metrics.js
dom/workers/WorkerDebugger.cpp
toolkit/components/perfmonitoring/PerformanceMetricsCollector.cpp
--- a/dom/base/DocGroup.cpp
+++ b/dom/base/DocGroup.cpp
@@ -73,65 +73,64 @@ DocGroup::ReportPerformanceInfo()
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(mPerformanceCounter);
 #if defined(XP_WIN)
   uint32_t pid = GetCurrentProcessId();
 #else
   uint32_t pid = getpid();
 #endif
-  uint64_t wid = 0;
   uint64_t pwid = 0;
   uint16_t count = 0;
   uint64_t duration = 0;
+  bool isTopLevel = false;
   nsCString host = NS_LITERAL_CSTRING("None");
 
+  // iterating on documents until we find the top window
   for (const auto& document : *this) {
-    // grabbing the host name of the first document
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
     MOZ_ASSERT(doc);
-    nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
-    if (!docURI) {
-      continue;
-    }
-    docURI->GetHost(host);
-    wid = doc->OuterWindowID();
 
-    // getting the top window id - if not possible
-    // pwid gets the same value than wid
-    pwid = wid;
+    // looking for the top window id
     nsPIDOMWindowInner* win = doc->GetInnerWindow();
     if (win) {
       nsPIDOMWindowOuter* outer = win->GetOuterWindow();
       if (outer) {
         nsCOMPtr<nsPIDOMWindowOuter> top = outer->GetTop();
         if (top) {
           pwid = top->WindowID();
+          isTopLevel = doc->OuterWindowID() == pwid;
+          nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
+          if (!docURI) {
+            continue;
+          }
+          docURI->GetHost(host);
+          break;
         }
       }
     }
   }
 
   duration = mPerformanceCounter->GetExecutionDuration();
   FallibleTArray<CategoryDispatch> items;
 
   // now that we have the host and window ids, let's look at the perf counters
   for (uint32_t index = 0; index < (uint32_t)TaskCategory::Count; index++) {
     TaskCategory category = static_cast<TaskCategory>(index);
     count = mPerformanceCounter->GetDispatchCount(DispatchCategory(category));
     CategoryDispatch item = CategoryDispatch(index, count);
     if (!items.AppendElement(item, fallible)) {
       NS_ERROR("Could not complete the operation");
-      return PerformanceInfo(host, pid, wid, pwid, duration, false, items);
+      return PerformanceInfo(host, pid, pwid, duration, false, isTopLevel, items);
     }
   }
 
   // setting back all counters to zero
   mPerformanceCounter->ResetPerformanceCounters();
-  return PerformanceInfo(host, pid, wid, pwid, duration, false, items);
+  return PerformanceInfo(host, pid, pwid, duration, false, isTopLevel, items);
 }
 
 nsresult
 DocGroup::Dispatch(TaskCategory aCategory,
                    already_AddRefed<nsIRunnable>&& aRunnable)
 {
   if (mPerformanceCounter) {
     mPerformanceCounter->IncrementDispatchCounter(DispatchCategory(aCategory));
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -363,22 +363,22 @@ partial namespace ChromeUtils {
  */
 dictionary CategoryDispatchDictionary
 {
   unsigned short category = 0;
   unsigned short count = 0;
 };
 
 dictionary PerformanceInfoDictionary {
-  DOMString host = "";
+  ByteString host = "";
   unsigned long pid = 0;
-  unsigned long long wid = 0;
-  unsigned long long pwid = 0;
+  unsigned long long windowId = 0;
   unsigned long long duration = 0;
-  boolean worker = false;
+  boolean isWorker = false;
+  boolean isTopLevel = false;
   sequence<CategoryDispatchDictionary> items = [];
 };
 
 /**
  * Used by requestIOActivity() to return the number of bytes
  * that were read (rx) and/or written (tx) for a given location.
  *
  * Locations can be sockets or files.
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -127,17 +127,17 @@ struct CreatedWindowInfo
   DimensionInfo dimensions;
 };
 
 
 /**
  * PerformanceInfo is used to pass performance info stored
  * in WorkerPrivate & DocGroup instances
  *
- * Each (host, pid, wid, pwid) is unique to a given DocGroup or
+ * Each (host, pid, windowId) is unique to a given DocGroup or
  * Worker, and we collect the number of dispatches per Dispatch
  * category and total execution duration.
  *
  * This IPDL struct reflects the data collected in Performance counters.
  * see xpcom/threads/PerformanceCounter.h
  */
 struct CategoryDispatch
 {
@@ -149,21 +149,21 @@ struct CategoryDispatch
 
 struct PerformanceInfo
 {
   // Host of the document, if any
   nsCString host;
   // process id
   uint32_t pid;
   // window id
-  uint64_t wid;
-  // "parent" window id
-  uint64_t pwid;
+  uint64_t windowId;
   // Execution time in microseconds
   uint64_t duration;
   // True if the data is collected in a worker
-  bool worker;
+  bool isWorker;
+  // True if the document window is the top window 
+  bool isTopLevel;
   // Counters per category. For workers, a single entry
   CategoryDispatch[] items;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/tests/browser/browser_test_performance_metrics.js
+++ b/dom/tests/browser/browser_test_performance_metrics.js
@@ -62,31 +62,35 @@ add_task(async function test() {
   // load a 4th tab with a worker
   await BrowserTestUtils.withNewTab({ gBrowser, url: WORKER_URL },
     async function(browser) {
     // grab events..
     let worker_duration = 0;
     let worker_total = 0;
     let duration = 0;
     let total = 0;
+    let isTopLevel = false;
 
     function exploreResults(data) {
       for (let entry of data) {
+        if (entry.host == "example.com" && entry.isTopLevel) {
+          isTopLevel = true;
+        }
         if (entry.pid == Services.appinfo.processID) {
           parent_process_event = true;
         }
-        if (entry.worker) {
+        if (entry.isWorker) {
           worker_event = true;
           worker_duration += entry.duration;
         } else {
           duration += entry.duration;
         }
         // let's look at the data we got back
         for (let item of entry.items) {
-          if (entry.worker) {
+          if (entry.isWorker) {
             worker_total += item.count;
           } else {
             total += item.count;
           }
         }
       }
     }
 
@@ -94,15 +98,16 @@ add_task(async function test() {
     let results = await ChromeUtils.requestPerformanceMetrics();
     exploreResults(results);
 
     Assert.ok(worker_duration > 0, "Worker duration should be positive");
     Assert.ok(worker_total > 0, "Worker count should be positive");
     Assert.ok(duration > 0, "Duration should be positive");
     Assert.ok(total > 0, "Should get a positive count");
     Assert.ok(parent_process_event, "parent process sent back some events");
+    Assert.ok(isTopLevel, "example.com as a top level window");
   });
 
   BrowserTestUtils.removeTab(page1);
   BrowserTestUtils.removeTab(page2);
   BrowserTestUtils.removeTab(page3);
   SpecialPowers.clearUserPref('dom.performance.enable_scheduler_timing');
 });
--- a/dom/workers/WorkerDebugger.cpp
+++ b/dom/workers/WorkerDebugger.cpp
@@ -479,25 +479,28 @@ WorkerDebugger::ReportPerformanceInfo()
 {
   AssertIsOnMainThread();
 
 #if defined(XP_WIN)
   uint32_t pid = GetCurrentProcessId();
 #else
   uint32_t pid = getpid();
 #endif
+  bool isTopLevel= false;
   uint64_t wid = mWorkerPrivate->WindowID();
-  uint64_t pwid = wid;
+  uint64_t pwid = 0;
+
   nsPIDOMWindowInner* win = mWorkerPrivate->GetWindow();
   if (win) {
     nsPIDOMWindowOuter* outer = win->GetOuterWindow();
     if (outer) {
       nsCOMPtr<nsPIDOMWindowOuter> top = outer->GetTop();
       if (top) {
         pwid = top->WindowID();
+        isTopLevel = pwid == mWorkerPrivate->WindowID();
       }
     }
   }
 
 
   // Workers only produce metrics for a single category - DispatchCategory::Worker.
   // We still return an array of CategoryDispatch so the PerformanceInfo
   // struct is common to all performance counters throughout Firefox.
@@ -508,20 +511,20 @@ WorkerDebugger::ReportPerformanceInfo()
 
   RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
   if (perf) {
     count =  perf->GetTotalDispatchCount();
     duration = perf->GetExecutionDuration();
     CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
     if (!items.AppendElement(item, fallible)) {
       NS_ERROR("Could not complete the operation");
-      return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
-                            true, items);
+      return PerformanceInfo(uri->GetSpecOrDefault(), pid, pwid, duration,
+                            true, isTopLevel, items);
     }
     perf->ResetPerformanceCounters();
   }
 
-  return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
-                         true, items);
+  return PerformanceInfo(uri->GetSpecOrDefault(), pid, pwid, duration,
+                         true, isTopLevel, items);
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/toolkit/components/perfmonitoring/PerformanceMetricsCollector.cpp
+++ b/toolkit/components/perfmonitoring/PerformanceMetricsCollector.cpp
@@ -73,21 +73,21 @@ AggregatedResults::AppendResult(const ns
     }
 
     PerformanceInfoDictionary* data = mData.AppendElement(fallible);
     if (NS_WARN_IF(!data)) {
       Abort(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     data->mPid = result.pid();
-    data->mWid = result.wid();
-    data->mPwid = result.pwid();
-    data->mHost = *result.host().get();
+    data->mWindowId = result.windowId();
+    data->mHost.Assign(result.host());
     data->mDuration = result.pid();
-    data->mWorker = result.worker();
+    data->mIsWorker = result.isWorker();
+    data->mIsTopLevel = result.isTopLevel();
     data->mItems = items;
   }
 
   mPendingResults--;
   if (mPendingResults) {
     return;
   }