Bug 1457127 - Create common helpers for taking keyed histogram snapshots. r?chutten,janerik draft
authorAlessio Placitelli <alessio.placitelli@gmail.com>
Wed, 16 May 2018 13:09:33 +0200
changeset 797013 ce886f36d4965c776acdd866c2c5ab5ce5fe117f
parent 797012 308147ead26c1969e534b6c97d63e54e3f5918fc
child 797014 1c0952d5366445713f95c490b787967cebc591f1
push id110396
push userbmo:alessio.placitelli@gmail.com
push dateFri, 18 May 2018 15:30:15 +0000
reviewerschutten, janerik
bugs1457127
milestone62.0a1
Bug 1457127 - Create common helpers for taking keyed histogram snapshots. r?chutten,janerik MozReview-Commit-ID: 3JrMtOrefdS
toolkit/components/telemetry/TelemetryHistogram.cpp
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -166,16 +166,24 @@ struct HistogramSnapshotInfo {
 };
 
 typedef mozilla::Vector<HistogramSnapshotInfo> HistogramSnapshotsArray;
 typedef mozilla::Vector<HistogramSnapshotsArray> HistogramProcessSnapshotsArray;
 
 // The following is used to handle snapshot information for keyed histograms.
 typedef nsDataHashtable<nsCStringHashKey, HistogramSnapshotData> KeyedHistogramSnapshotData;
 
+struct KeyedHistogramSnapshotInfo {
+  KeyedHistogramSnapshotData data;
+  HistogramID histogramId;
+};
+
+typedef mozilla::Vector<KeyedHistogramSnapshotInfo> KeyedHistogramSnapshotsArray;
+typedef mozilla::Vector<KeyedHistogramSnapshotsArray> KeyedHistogramProcessSnapshotsArray;
+
 class KeyedHistogram {
 public:
   KeyedHistogram(HistogramID id, const HistogramInfo& info);
   ~KeyedHistogram();
   nsresult GetHistogram(const nsCString& name, Histogram** histogram);
   Histogram* GetHistogram(const nsCString& name);
   uint32_t GetHistogramType() const { return mHistogramInfo.histogramType; }
   nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args);
@@ -1043,16 +1051,80 @@ KeyedHistogram::GetSnapshot(const Static
 
   if (aClearSubsession) {
     Clear();
   }
 
   return NS_OK;
 }
 
+
+/**
+ * Helper function to get a snapshot of the keyed histograms.
+ *
+ * @param {aLock} the lock proof.
+ * @param {aDataset} the dataset for which the snapshot is being requested.
+ * @param {aClearSubsession} whether or not to clear the data after
+ *        taking the snapshot.
+ * @param {aIncludeGPU} whether or not to include data for the GPU.
+ * @param {aOutSnapshot} the container in which the snapshot data will be stored.
+ * @return {nsresult} NS_OK if the snapshot was successfully taken or
+ *         NS_ERROR_OUT_OF_MEMORY if it failed to allocate memory.
+ */
+nsresult
+internal_GetKeyedHistogramsSnapshot(const StaticMutexAutoLock& aLock,
+                                    unsigned int aDataset,
+                                    bool aClearSubsession,
+                                    bool aIncludeGPU,
+                                    KeyedHistogramProcessSnapshotsArray& aOutSnapshot)
+{
+  if (!aOutSnapshot.resize(static_cast<uint32_t>(ProcessID::Count))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
+    KeyedHistogramSnapshotsArray& hArray = aOutSnapshot[process];
+
+    for (size_t i = 0; i < HistogramCount; ++i) {
+      HistogramID id = HistogramID(i);
+      const HistogramInfo& info = gHistogramInfos[id];
+      if (!info.keyed) {
+        continue;
+      }
+
+      if (!CanRecordInProcess(info.record_in_processes, ProcessID(process)) ||
+        ((ProcessID(process) == ProcessID::Gpu) && !aIncludeGPU)) {
+        continue;
+      }
+
+      if (!IsInDataset(info.dataset, aDataset)) {
+        continue;
+      }
+
+      KeyedHistogram* keyed = internal_GetKeyedHistogramById(id,
+                                                             ProcessID(process),
+                                                             /* instantiate = */ false);
+      if (!keyed) {
+        continue;
+      }
+
+      // Take a snapshot of the keyed histogram data!
+      KeyedHistogramSnapshotData snapshot;
+      if (!NS_SUCCEEDED(keyed->GetSnapshot(aLock, snapshot, aClearSubsession))) {
+        return NS_ERROR_FAILURE;
+      }
+
+      if (!hArray.emplaceBack(KeyedHistogramSnapshotInfo{mozilla::Move(snapshot), id})) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+    }
+  }
+  return NS_OK;
+}
+
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //
 // PRIVATE: thread-unsafe helpers for the external interface
 
 namespace {
@@ -2365,83 +2437,42 @@ TelemetryHistogram::GetKeyedHistogramSna
 
   // Include the GPU process in histogram snapshots only if we actually tried
   // to launch a process for it.
   bool includeGPUProcess = false;
   if (auto gpm = mozilla::gfx::GPUProcessManager::Get()) {
     includeGPUProcess = gpm->AttemptedGPUProcess();
   }
 
-  struct KeyedHistogramProcessInfo {
-    KeyedHistogramSnapshotData data;
-    HistogramID histogramId;
-  };
-
   // Get a snapshot of all the data while holding the mutex.
-  mozilla::Vector<mozilla::Vector<KeyedHistogramProcessInfo>> dataSnapshot;
+  KeyedHistogramProcessSnapshotsArray processHistArray;
   {
-    if (!dataSnapshot.resize(static_cast<uint32_t>(ProcessID::Count))) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
     StaticMutexAutoLock locker(gTelemetryHistogramMutex);
-
-    for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
-      mozilla::Vector<KeyedHistogramProcessInfo>& hArray = dataSnapshot[process];
-
-      for (size_t i = 0; i < HistogramCount; ++i) {
-        HistogramID id = HistogramID(i);
-        const HistogramInfo& info = gHistogramInfos[id];
-        if (!info.keyed) {
-          continue;
-        }
-
-        if (!CanRecordInProcess(info.record_in_processes, ProcessID(process)) ||
-          ((ProcessID(process) == ProcessID::Gpu) && !includeGPUProcess)) {
-          continue;
-        }
-
-        if (!IsInDataset(info.dataset, aDataset)) {
-          continue;
-        }
-
-        KeyedHistogram* keyed = internal_GetKeyedHistogramById(id,
-                                                               ProcessID(process),
-                                                               /* instantiate = */ false);
-        if (!keyed) {
-          continue;
-        }
-
-        // Take a snapshot of the keyed histogram data!
-        KeyedHistogramSnapshotData snapshot;
-        if (!NS_SUCCEEDED(keyed->GetSnapshot(locker, snapshot, aClearSubsession))) {
-          return NS_ERROR_FAILURE;
-        }
-
-        if (!hArray.emplaceBack(KeyedHistogramProcessInfo{mozilla::Move(snapshot), id})) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-      }
+    nsresult rv = internal_GetKeyedHistogramsSnapshot(locker,
+                                                      aDataset,
+                                                      aClearSubsession,
+                                                      includeGPUProcess,
+                                                      processHistArray);
+    if (NS_FAILED(rv)) {
+      return rv;
     }
   }
 
   // Mirror the snapshot data to JS, now that we released the mutex.
-  for (uint32_t process = 0; process < dataSnapshot.length(); ++process) {
-    const mozilla::Vector<KeyedHistogramProcessInfo>& hArray = dataSnapshot[process];
-
+  for (uint32_t process = 0; process < processHistArray.length(); ++process) {
     JS::Rooted<JSObject*> processObject(aCx, JS_NewPlainObject(aCx));
     if (!processObject) {
       return NS_ERROR_FAILURE;
     }
     if (!JS_DefineProperty(aCx, obj, GetNameForProcessID(ProcessID(process)),
                            processObject, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
-    for (size_t i = 0; i < hArray.length(); ++i) {
-      const KeyedHistogramProcessInfo& hData = hArray[i];
+
+    for (const KeyedHistogramSnapshotInfo& hData : processHistArray[process]) {
       const HistogramInfo& info = gHistogramInfos[hData.histogramId];
 
       JS::RootedObject snapshot(aCx, JS_NewPlainObject(aCx));
       if (!snapshot) {
         return NS_ERROR_FAILURE;
       }
 
       if (!NS_SUCCEEDED(internal_ReflectKeyedHistogram(hData.data, info, aCx, snapshot))) {