Bug 1447768 - part 1 - Add PerformanceUtils helpers - r?baku draft
authorTarek Ziadé <tarek@mozilla.com>
Wed, 04 Apr 2018 10:12:02 +0200
changeset 777205 6bc72399653f17e85ec686f7d06a4b6b24b08539
parent 772787 de32269720d056972b85f4eec5f0a8286de6e3af
child 777206 9a47ac09041071e35e625839b15ed90e4cf98739
push id105106
push usertziade@mozilla.com
push dateWed, 04 Apr 2018 11:39:15 +0000
reviewersbaku
bugs1447768
milestone61.0a1
Bug 1447768 - part 1 - Add PerformanceUtils helpers - r?baku This new module simplifies how we interact with PerformanceInfo counters: - CollectPerformanceInfo: returns all PerformanceInfo instances - NotifyPerformanceInfo: converts PerformanceInfo in XPCOM and notify them MozReview-Commit-ID: JedKEtsbQTF
dom/base/nsPerformanceMetrics.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
toolkit/components/perfmonitoring/PerformanceUtils.cpp
toolkit/components/perfmonitoring/PerformanceUtils.h
toolkit/components/perfmonitoring/moz.build
--- a/dom/base/nsPerformanceMetrics.h
+++ b/dom/base/nsPerformanceMetrics.h
@@ -2,17 +2,19 @@
 /* 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/. */
 
 #ifndef nsPerformanceMetrics_h___
 #define nsPerformanceMetrics_h___
 
+#include "nsCOMArray.h"
 #include "nsIPerformanceMetrics.h"
+#include "nsString.h"
 
 
 class PerformanceMetricsDispatchCategory final : public nsIPerformanceMetricsDispatchCategory
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPERFORMANCEMETRICSDISPATCHCATEGORY
   PerformanceMetricsDispatchCategory(uint32_t aCategory, uint32_t aCount);
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -64,29 +64,31 @@
 #include "mozilla/layers/CompositorManagerChild.h"
 #include "mozilla/layers/ContentProcessController.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layout/RenderFrameChild.h"
 #include "mozilla/loader/ScriptCacheActors.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/CaptivePortalService.h"
+#ifndef RELEASE_OR_BETA
+#include "mozilla/PerformanceUtils.h"
+#endif
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "mozilla/HangDetails.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
 #include "NullPrincipal.h"
-#include "nsIPerformanceMetrics.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIWorkerDebuggerManager.h"
 
 #if !defined(XP_WIN)
 #include "mozilla/Omnijar.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
@@ -1383,37 +1385,19 @@ ContentChild::GetResultForRenderingInitF
   gfxCriticalNote << "Could not initialize rendering with GPU process";
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvRequestPerformanceMetrics()
 {
 #ifndef RELEASE_OR_BETA
-  // iterate on all WorkerDebugger
-  RefPtr<WorkerDebuggerManager> wdm = WorkerDebuggerManager::GetOrCreate();
-  if (NS_WARN_IF(!wdm)) {
-    return IPC_OK();
-  }
-
-  for (uint32_t index = 0; index < wdm->GetDebuggersLength(); index++) {
-    WorkerDebugger* debugger = wdm->GetDebuggerAt(index);
-    MOZ_ASSERT(debugger);
-    SendAddPerformanceMetrics(debugger->ReportPerformanceInfo());
-  }
-
-  // iterate on all DocGroup
-  nsTArray<RefPtr<TabChild>> tabs = TabChild::GetAll();
-  for (const auto& tabChild : tabs) {
-    TabGroup* tabGroup = tabChild->TabGroup();
-    for (auto iter = tabGroup->Iter(); !iter.Done(); iter.Next()) {
-        RefPtr<DocGroup> docGroup = iter.Get()->mDocGroup;
-        SendAddPerformanceMetrics(docGroup->ReportPerformanceInfo());
-    }
-  }
+  nsTArray<PerformanceInfo> info;
+  CollectPerformanceInfo(info);
+  SendAddPerformanceMetrics(info);
   return IPC_OK();
 #endif
 #ifdef RELEASE_OR_BETA
   return IPC_OK();
 #endif
 }
 
 mozilla::ipc::IPCResult
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -178,29 +178,29 @@
 #include "nsOpenURIInFrameParams.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "prio.h"
 #include "private/pprio.h"
 #include "ContentProcessManager.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
+#ifndef RELEASE_OR_BETA
+#include "mozilla/PerformanceUtils.h"
+#endif
 #include "mozilla/psm/PSMContentListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginTags.h"
 #include "nsIBlocklistService.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsICaptivePortalService.h"
 #include "nsIObjectLoadingContent.h"
-#include "nsPerformanceMetrics.h"
-
 #include "nsIBidiKeyboard.h"
-
 #include "nsLayoutStylesheetCache.h"
 
 #include "mozilla/Sprintf.h"
 
 #ifdef MOZ_WEBRTC
 #include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
@@ -3318,51 +3318,22 @@ ContentParent::RecvFinishMemoryReport(co
   if (mMemoryReportRequest) {
     mMemoryReportRequest->Finish(aGeneration);
     mMemoryReportRequest = nullptr;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvAddPerformanceMetrics(const PerformanceInfo& aMetrics)
+ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
 {
 #ifndef RELEASE_OR_BETA
-  // converting the data we get from a child as a notification
-  if (aMetrics.items().IsEmpty()) {
-      return IPC_OK();
-  }
-
-  nsCOMPtr<nsIMutableArray> xpItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
-  if (NS_WARN_IF(!xpItems)) {
-    return IPC_FAIL_NO_REASON(this);
-  }
-
-  for (uint32_t i = 0; i<aMetrics.items().Length(); i++) {
-       const CategoryDispatch& entry = aMetrics.items()[i];
-       nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item =
-           new PerformanceMetricsDispatchCategory(entry.category(),
-                                                  entry.count());
-       xpItems->AppendElement(item);
-  }
-
-  nsCOMPtr<nsIPerformanceMetricsData> data =
-      new PerformanceMetricsData(aMetrics.pid(), aMetrics.wid(), aMetrics.pwid(),
-                                 aMetrics.host(), aMetrics.duration(),
-                                 aMetrics.worker(), xpItems);
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (!obs) {
-    return IPC_FAIL_NO_REASON(this);
-  }
-  obs->NotifyObservers(data, "performance-metrics", nullptr);
+  Unused << NS_WARN_IF(NS_FAILED(mozilla::NotifyPerformanceInfo(aMetrics)));
+#endif
   return IPC_OK();
-#endif
-#ifdef RELEASE_OR_BETA
-  return IPC_OK();
-#endif
 }
 
 PCycleCollectWithLogsParent*
 ContentParent::AllocPCycleCollectWithLogsParent(const bool& aDumpAllTraces,
                                                 const FileDescriptor& aGCLog,
                                                 const FileDescriptor& aCCLog)
 {
   MOZ_CRASH("Don't call this; use ContentParent::CycleCollectWithLogs");
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -843,17 +843,17 @@ private:
    * Get or create the corresponding content parent array to |aContentProcessType|.
    */
   static nsTArray<ContentParent*>& GetOrCreatePool(const nsAString& aContentProcessType);
 
   virtual mozilla::ipc::IPCResult RecvInitBackground(Endpoint<mozilla::ipc::PBackgroundParent>&& aEndpoint) override;
 
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
-  mozilla::ipc::IPCResult RecvAddPerformanceMetrics(const PerformanceInfo& aMetrics) override;
+  mozilla::ipc::IPCResult RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics) override;
 
   virtual bool
   DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
 
   virtual bool
   DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) override;
 
   virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1131,17 +1131,17 @@ parent:
 
     async AddMemoryReport(MemoryReport aReport);
     async FinishMemoryReport(uint32_t aGeneration);
 
     async MaybeReloadPlugins();
 
     async BHRThreadHang(HangDetails aHangDetails);
 
-    async AddPerformanceMetrics(PerformanceInfo aMetrics);
+    async AddPerformanceMetrics(PerformanceInfo[] aMetrics);
 both:
      async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
                         Principal aPrincipal, ClonedMessageData aData);
 
     /**
      * Notify `push-subscription-modified` observers in the parent and child.
      */
     async NotifyPushSubscriptionModifiedObservers(nsCString scope,
new file mode 100644
--- /dev/null
+++ b/toolkit/components/perfmonitoring/PerformanceUtils.cpp
@@ -0,0 +1,90 @@
+/* -*- 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 "nsIMutableArray.h"
+#include "nsPerformanceMetrics.h"
+#include "nsThreadUtils.h"
+#include "mozilla/PerformanceUtils.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/WorkerDebugger.h"
+#include "mozilla/dom/WorkerDebuggerManager.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+namespace mozilla {
+
+void
+CollectPerformanceInfo(nsTArray<PerformanceInfo>& aMetrics)
+{
+  // collecting ReportPerformanceInfo from all DocGroup instances
+  for (const auto& tabChild : TabChild::GetAll()) {
+    TabGroup* tabGroup = tabChild->TabGroup();
+    for (auto iter = tabGroup->Iter(); !iter.Done(); iter.Next()) {
+      DocGroup* docGroup = iter.Get()->mDocGroup;
+      aMetrics.AppendElement(docGroup->ReportPerformanceInfo());
+    }
+  }
+
+  // collecting ReportPerformanceInfo from all WorkerDebugger instances
+  RefPtr<mozilla::dom::WorkerDebuggerManager> wdm = WorkerDebuggerManager::GetOrCreate();
+  if (NS_WARN_IF(!wdm)) {
+    return;
+  }
+  for (uint32_t i = 0; i < wdm->GetDebuggersLength(); i++) {
+    WorkerDebugger* debugger = wdm->GetDebuggerAt(i);
+    aMetrics.AppendElement(debugger->ReportPerformanceInfo());
+  }
+}
+
+nsresult
+NotifyPerformanceInfo(const nsTArray<PerformanceInfo>& aMetrics)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  if (NS_WARN_IF(!array)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Each PerformanceInfo is converted into a nsIPerformanceMetricsData
+  for (const PerformanceInfo& info : aMetrics) {
+    nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
+    if (NS_WARN_IF(!items)) {
+      return rv;
+    }
+    for (const CategoryDispatch& entry : info.items()) {
+      nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item =
+        new PerformanceMetricsDispatchCategory(entry.category(),
+                                               entry.count());
+      rv = items->AppendElement(item);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+    nsCOMPtr<nsIPerformanceMetricsData> data;
+    data = new PerformanceMetricsData(info.pid(), info.wid(), info.pwid(),
+                                      info.host(), info.duration(),
+                                      info.worker(), items);
+    rv = array->AppendElement(data);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (NS_WARN_IF(!obs)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = obs->NotifyObservers(array, "performance-metrics", nullptr);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
+}
+
+} // namespace
new file mode 100644
--- /dev/null
+++ b/toolkit/components/perfmonitoring/PerformanceUtils.h
@@ -0,0 +1,26 @@
+/* -*- 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 PerformanceCollector_h
+#define PerformanceCollector_h
+
+#include "mozilla/dom/DOMTypes.h"   // defines PerformanceInfo
+
+namespace mozilla {
+
+/**
+ * Collects all performance info in the current process
+ * and adds then in the aMetrics arrey
+ */
+void CollectPerformanceInfo(nsTArray<dom::PerformanceInfo>& aMetrics);
+
+/**
+ * Converts a PerformanceInfo array into a nsIPerformanceMetricsData and
+ * sends a performance-metrics notification with it
+ */
+nsresult NotifyPerformanceInfo(const nsTArray<dom::PerformanceInfo>& aMetrics);
+
+} // namespace mozilla
+#endif   // PerformanceCollector_h
--- a/toolkit/components/perfmonitoring/moz.build
+++ b/toolkit/components/perfmonitoring/moz.build
@@ -21,17 +21,28 @@ EXTRA_JS_MODULES += [
 XPIDL_SOURCES += [
     'nsIPerformanceStats.idl',
 ]
 
 UNIFIED_SOURCES += [
     'nsPerformanceStats.cpp'
 ]
 
+if not CONFIG['RELEASE_OR_BETA']:
+    UNIFIED_SOURCES += [
+        'PerformanceUtils.cpp'
+    ]
+
+    EXPORTS.mozilla += [
+        'PerformanceUtils.h'
+    ]
+
 EXPORTS += [
     'nsPerformanceStats.h'
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
+
+include('/ipc/chromium/chromium-config.mozbuild')