Bug 1320052 - Unify histogram storage into a single container. r?chutten draft
authorJan-Erik Rediger <jrediger@mozilla.com>
Wed, 02 May 2018 15:43:02 +0200
changeset 791447 799c64b6cfb4e43215bed2b9d7c3ccd0afc38723
parent 789701 0b0b7c7560bae92177d1c2f293e77e8cccd91d44
child 791448 1768d82c088761f1dfce6ec06ebdda0b8bb2d1cd
push id108818
push userbmo:jrediger@mozilla.com
push dateFri, 04 May 2018 13:17:24 +0000
reviewerschutten
bugs1320052
milestone61.0a1
Bug 1320052 - Unify histogram storage into a single container. r?chutten On Desktop and GeckoView we only ever need to store histograms for a subsession and clear the histograms when a snapshot is done (e.g. a main ping is built). On Fennec we don't have subsessions and only store for a session and never clear the storage. MozReview-Commit-ID: BeVi86kZPs2
toolkit/components/telemetry/Telemetry.cpp
toolkit/components/telemetry/TelemetryHistogram.cpp
toolkit/components/telemetry/TelemetryHistogram.h
toolkit/components/telemetry/TelemetrySession.jsm
toolkit/components/telemetry/nsITelemetry.idl
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -572,42 +572,30 @@ TelemetryImpl::AddSQLInfo(JSContext *cx,
 
 NS_IMETHODIMP
 TelemetryImpl::SetHistogramRecordingEnabled(const nsACString &id, bool aEnabled)
 {
   return TelemetryHistogram::SetHistogramRecordingEnabled(id, aEnabled);
 }
 
 NS_IMETHODIMP
-TelemetryImpl::SnapshotHistograms(unsigned int aDataset, bool aSubsession,
+TelemetryImpl::SnapshotHistograms(unsigned int aDataset,
                                   bool aClearHistograms, JSContext* aCx,
                                   JS::MutableHandleValue aResult)
 {
-#if defined(MOZ_WIDGET_ANDROID)
-  if (aSubsession) {
-    return NS_OK;
-  }
-#endif
   return TelemetryHistogram::CreateHistogramSnapshots(aCx, aResult, aDataset,
-                                                      aSubsession,
                                                       aClearHistograms);
 }
 
 NS_IMETHODIMP
-TelemetryImpl::SnapshotKeyedHistograms(unsigned int aDataset, bool aSubsession,
+TelemetryImpl::SnapshotKeyedHistograms(unsigned int aDataset,
                                        bool aClearHistograms, JSContext* aCx,
                                        JS::MutableHandleValue aResult)
 {
-#if defined(MOZ_WIDGET_ANDROID)
-  if (aSubsession) {
-    return NS_OK;
-  }
-#endif
   return TelemetryHistogram::GetKeyedHistogramSnapshots(aCx, aResult, aDataset,
-                                                        aSubsession,
                                                         aClearHistograms);
 }
 
 bool
 TelemetryImpl::GetSQLStats(JSContext *cx, JS::MutableHandle<JS::Value> ret, bool includePrivateSql)
 {
   JS::Rooted<JSObject*> root_obj(cx, JS_NewPlainObject(cx));
   if (!root_obj)
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -139,45 +139,36 @@ struct HistogramInfo {
   bool allows_key(const nsACString& key) const;
 };
 
 enum reflectStatus {
   REFLECT_OK,
   REFLECT_FAILURE
 };
 
-enum class SessionType {
-  Session = 0,
-  Subsession = 1,
-  Count,
-};
-
 class KeyedHistogram {
 public:
   KeyedHistogram(HistogramID id, const HistogramInfo& info);
   ~KeyedHistogram();
-  nsresult GetHistogram(const nsCString& name, Histogram** histogram, bool subsession);
-  Histogram* GetHistogram(const nsCString& name, bool subsession);
+  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);
   nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj,
-                         bool subsession, bool clearSubsession);
+                         bool clearSubsession);
 
   nsresult Add(const nsCString& key, uint32_t aSample, ProcessID aProcessType);
-  void Clear(bool subsession);
+  void Clear();
 
   HistogramID GetHistogramID() const { return mId; }
 
 private:
   typedef nsBaseHashtableET<nsCStringHashKey, Histogram*> KeyedHistogramEntry;
   typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType;
   KeyedHistogramMapType mHistogramMap;
-#if !defined(MOZ_WIDGET_ANDROID)
-  KeyedHistogramMapType mSubsessionMap;
-#endif
 
   static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry,
                                     JSContext* cx,
                                     JS::Handle<JSObject*> obj);
 
   const HistogramID mId;
   const HistogramInfo& mHistogramInfo;
 };
@@ -199,17 +190,16 @@ bool gInitDone = false;
 bool gCanRecordBase = false;
 // Whether we are collecting the extended, opt-in, Histogram data.
 bool gCanRecordExtended = false;
 
 // The storage for actual Histogram instances.
 // We use separate ones for plain and keyed histograms.
 Histogram** gHistogramStorage;
 // Keyed histograms internally map string keys to individual Histogram instances.
-// KeyedHistogram keeps track of session & subsession histograms internally.
 KeyedHistogram** gKeyedHistogramStorage;
 
 // Cache of histogram name to a histogram id.
 StringToHistogramIdMap gNameToHistogramIDMap(HistogramCount);
 
 // To simplify logic below we use a single histogram instance for all expired histograms.
 Histogram* gExpiredHistogram = nullptr;
 
@@ -251,47 +241,41 @@ namespace {
 
 size_t internal_KeyedHistogramStorageIndex(HistogramID aHistogramId,
                                            ProcessID aProcessId)
 {
   return aHistogramId * size_t(ProcessID::Count) + size_t(aProcessId);
 }
 
 size_t internal_HistogramStorageIndex(HistogramID aHistogramId,
-                                      ProcessID aProcessId,
-                                      SessionType aSessionType)
+                                      ProcessID aProcessId)
 {
   static_assert(
     HistogramCount <
-      std::numeric_limits<size_t>::max() / size_t(ProcessID::Count) / size_t(SessionType::Count),
-        "Too many histograms, processes, and session types to store in a 1D "
-        "array.");
+      std::numeric_limits<size_t>::max() / size_t(ProcessID::Count),
+        "Too many histograms and processes to store in a 1D array.");
 
-  return aHistogramId * size_t(ProcessID::Count) * size_t(SessionType::Count) +
-         size_t(aProcessId) * size_t(SessionType::Count) +
-         size_t(aSessionType);
+  return aHistogramId * size_t(ProcessID::Count) + size_t(aProcessId);
 }
 
 Histogram* internal_GetHistogramFromStorage(HistogramID aHistogramId,
-                                            ProcessID aProcessId,
-                                            SessionType aSessionType)
+                                            ProcessID aProcessId)
 {
-  size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId, aSessionType);
+  size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId);
   return gHistogramStorage[index];
 }
 
 void internal_SetHistogramInStorage(HistogramID aHistogramId,
                                     ProcessID aProcessId,
-                                    SessionType aSessionType,
                                     Histogram* aHistogram)
 {
   MOZ_ASSERT(XRE_IsParentProcess(),
     "Histograms are stored only in the parent process.");
 
-  size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId, aSessionType);
+  size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId);
   MOZ_ASSERT(!gHistogramStorage[index],
     "Mustn't overwrite storage without clearing it first.");
   gHistogramStorage[index] = aHistogram;
 }
 
 KeyedHistogram* internal_GetKeyedHistogramFromStorage(HistogramID aHistogramId,
                                                       ProcessID aProcessId)
 {
@@ -320,36 +304,32 @@ bool
 internal_IsHistogramEnumId(HistogramID aID)
 {
   static_assert(((HistogramID)-1 > 0), "ID should be unsigned.");
   return aID < HistogramCount;
 }
 
 // Look up a plain histogram by id.
 Histogram*
-internal_GetHistogramById(HistogramID histogramId, ProcessID processId, SessionType sessionType,
-                          bool instantiate = true)
+internal_GetHistogramById(HistogramID histogramId, ProcessID processId, bool instantiate = true)
 {
   MOZ_ASSERT(internal_IsHistogramEnumId(histogramId));
   MOZ_ASSERT(!gHistogramInfos[histogramId].keyed);
   MOZ_ASSERT(processId < ProcessID::Count);
-  MOZ_ASSERT(sessionType < SessionType::Count);
 
-  Histogram* h = internal_GetHistogramFromStorage(histogramId,
-                                                  processId,
-                                                  sessionType);
+  Histogram* h = internal_GetHistogramFromStorage(histogramId, processId);
   if (h || !instantiate) {
     return h;
   }
 
   const HistogramInfo& info = gHistogramInfos[histogramId];
   const int bucketsOffset = gHistogramBucketLowerBoundIndex[histogramId];
   h = internal_CreateHistogramInstance(info, bucketsOffset);
   MOZ_ASSERT(h);
-  internal_SetHistogramInStorage(histogramId, processId, sessionType, h);
+  internal_SetHistogramInStorage(histogramId, processId, h);
   return h;
 }
 
 // Look up a keyed histogram by id.
 KeyedHistogram*
 internal_GetKeyedHistogramById(HistogramID histogramId, ProcessID processId,
                                bool instantiate = true)
 {
@@ -379,19 +359,19 @@ internal_GetHistogramIdByName(const nsAC
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   return NS_OK;
 }
 
 // Clear a histogram from storage.
 void
-internal_ClearHistogramById(HistogramID histogramId, ProcessID processId, SessionType sessionType)
+internal_ClearHistogramById(HistogramID histogramId, ProcessID processId)
 {
-  size_t index = internal_HistogramStorageIndex(histogramId, processId, sessionType);
+  size_t index = internal_HistogramStorageIndex(histogramId, processId);
   if (gHistogramStorage[index] == gExpiredHistogram) {
     // We keep gExpiredHistogram until TelemetryHistogram::DeInitializeGlobalState
     return;
   }
   delete gHistogramStorage[index];
   gHistogramStorage[index] = nullptr;
 }
 
@@ -623,18 +603,16 @@ internal_HistogramAdd(Histogram& histogr
   // as large values (instead of negative ones).
   if (value > INT_MAX) {
     TelemetryScalar::Add(
       mozilla::Telemetry::ScalarID::TELEMETRY_ACCUMULATE_CLAMPED_VALUES,
       NS_ConvertASCIItoUTF16(gHistogramInfos[id].name()), 1);
     value = INT_MAX;
   }
 
-  // It is safe to add to the histogram now: the subsession histogram was already
-  // cloned from this so we won't add the sample twice.
   histogram.Add(value);
 
   return NS_OK;
 }
 
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////
@@ -729,85 +707,65 @@ internal_ShouldReflectHistogram(Histogra
 ////////////////////////////////////////////////////////////////////////
 //
 // PRIVATE: class KeyedHistogram
 
 namespace {
 
 KeyedHistogram::KeyedHistogram(HistogramID id, const HistogramInfo& info)
   : mHistogramMap()
-#if !defined(MOZ_WIDGET_ANDROID)
-  , mSubsessionMap()
-#endif
   , mId(id)
   , mHistogramInfo(info)
 {
 }
 
 KeyedHistogram::~KeyedHistogram()
 {
   for (auto iter = mHistogramMap.Iter(); !iter.Done(); iter.Next()) {
     Histogram* h = iter.Get()->mData;
     if (h == gExpiredHistogram) {
       continue;
     }
     delete h;
   }
   mHistogramMap.Clear();
-
-#if !defined(MOZ_WIDGET_ANDROID)
-  for (auto iter = mSubsessionMap.Iter(); !iter.Done(); iter.Next()) {
-    Histogram* h = iter.Get()->mData;
-    if (h == gExpiredHistogram) {
-      continue;
-    }
-    delete h;
-  }
-  mSubsessionMap.Clear();
-#endif
 }
 
 nsresult
-KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram,
-                             bool subsession)
+KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram)
 {
-#if !defined(MOZ_WIDGET_ANDROID)
-  KeyedHistogramMapType& map = subsession ? mSubsessionMap : mHistogramMap;
-#else
-  KeyedHistogramMapType& map = mHistogramMap;
-#endif
-  KeyedHistogramEntry* entry = map.GetEntry(key);
+  KeyedHistogramEntry* entry = mHistogramMap.GetEntry(key);
   if (entry) {
     *histogram = entry->mData;
     return NS_OK;
   }
 
   int bucketsOffset = gHistogramBucketLowerBoundIndex[mId];
   Histogram* h = internal_CreateHistogramInstance(mHistogramInfo, bucketsOffset);
   if (!h) {
     return NS_ERROR_FAILURE;
   }
 
   h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
   *histogram = h;
 
-  entry = map.PutEntry(key);
+  entry = mHistogramMap.PutEntry(key);
   if (MOZ_UNLIKELY(!entry)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   entry->mData = h;
   return NS_OK;
 }
 
 Histogram*
-KeyedHistogram::GetHistogram(const nsCString& key, bool subsession)
+KeyedHistogram::GetHistogram(const nsCString& key)
 {
   Histogram* h = nullptr;
-  if (NS_FAILED(GetHistogram(key, &h, subsession))) {
+  if (NS_FAILED(GetHistogram(key, &h))) {
     return nullptr;
   }
   return h;
 }
 
 nsresult
 KeyedHistogram::Add(const nsCString& key, uint32_t sample,
                     ProcessID aProcessType)
@@ -822,66 +780,43 @@ KeyedHistogram::Add(const nsCString& key
     return NS_OK;
   }
 
   // Don't record if the current platform is not enabled
   if (!CanRecordPlatform(gHistogramInfos[mId].platforms)) {
     return NS_OK;
   }
 
-  Histogram* histogram = GetHistogram(key, false);
+  Histogram* histogram = GetHistogram(key);
   MOZ_ASSERT(histogram);
   if (!histogram) {
     return NS_ERROR_FAILURE;
   }
-#if !defined(MOZ_WIDGET_ANDROID)
-  Histogram* subsession = GetHistogram(key, true);
-  MOZ_ASSERT(subsession);
-  if (!subsession) {
-    return NS_ERROR_FAILURE;
-  }
-#endif
 
   // The internal representation of a base::Histogram's buckets uses `int`.
   // Clamp large values of `sample` to be INT_MAX so they continue to be treated
   // as large values (instead of negative ones).
   if (sample > INT_MAX) {
     TelemetryScalar::Add(
       mozilla::Telemetry::ScalarID::TELEMETRY_ACCUMULATE_CLAMPED_VALUES,
       NS_ConvertASCIItoUTF16(mHistogramInfo.name()), 1);
     sample = INT_MAX;
   }
 
   histogram->Add(sample);
-#if !defined(MOZ_WIDGET_ANDROID)
-  subsession->Add(sample);
-#endif
   return NS_OK;
 }
 
 void
-KeyedHistogram::Clear(bool onlySubsession)
+KeyedHistogram::Clear()
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   if (!XRE_IsParentProcess()) {
     return;
   }
-#if !defined(MOZ_WIDGET_ANDROID)
-  for (auto iter = mSubsessionMap.Iter(); !iter.Done(); iter.Next()) {
-    Histogram* h = iter.Get()->mData;
-    if (h == gExpiredHistogram) {
-      continue;
-    }
-    delete h;
-  }
-  mSubsessionMap.Clear();
-  if (onlySubsession) {
-    return;
-  }
-#endif
 
   for (auto iter = mHistogramMap.Iter(); !iter.Done(); iter.Next()) {
     Histogram* h = iter.Get()->mData;
     if (h == gExpiredHistogram) {
       continue;
     }
     delete h;
   }
@@ -932,33 +867,25 @@ KeyedHistogram::ReflectKeyedHistogram(Ke
                            histogramSnapshot, JSPROP_ENUMERATE)) {
     return false;
   }
 
   return true;
 }
 
 nsresult
-KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj,
-                              bool subsession, bool clearSubsession)
+KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, bool clearSubsession)
 {
-#if !defined(MOZ_WIDGET_ANDROID)
-  KeyedHistogramMapType& map = subsession ? mSubsessionMap : mHistogramMap;
-#else
-  KeyedHistogramMapType& map = mHistogramMap;
-#endif
-  if (!map.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
+  if (!mHistogramMap.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
     return NS_ERROR_FAILURE;
   }
 
-#if !defined(MOZ_WIDGET_ANDROID)
-  if (subsession && clearSubsession) {
-    Clear(true);
+  if (clearSubsession) {
+    Clear();
   }
-#endif
 
   return NS_OK;
 }
 
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
@@ -1008,25 +935,19 @@ internal_RemoteAccumulate(HistogramID aI
 
 void internal_Accumulate(HistogramID aId, uint32_t aSample)
 {
   if (!internal_CanRecordBase() ||
       internal_RemoteAccumulate(aId, aSample)) {
     return;
   }
 
-  Histogram *h = internal_GetHistogramById(aId, ProcessID::Parent, SessionType::Session);
+  Histogram *h = internal_GetHistogramById(aId, ProcessID::Parent);
   MOZ_ASSERT(h);
   internal_HistogramAdd(*h, aId, aSample, ProcessID::Parent);
-
-#if !defined(MOZ_WIDGET_ANDROID)
-  h = internal_GetHistogramById(aId, ProcessID::Parent, SessionType::Subsession);
-  MOZ_ASSERT(h);
-  internal_HistogramAdd(*h, aId, aSample, ProcessID::Parent);
-#endif
 }
 
 void
 internal_Accumulate(HistogramID aId,
                     const nsCString& aKey, uint32_t aSample)
 {
   if (!gInitDone || !internal_CanRecordBase() ||
       internal_RemoteAccumulate(aId, aKey, aSample)) {
@@ -1040,79 +961,57 @@ internal_Accumulate(HistogramID aId,
 
 void
 internal_AccumulateChild(ProcessID aProcessType, HistogramID aId, uint32_t aSample)
 {
   if (!internal_CanRecordBase()) {
     return;
   }
 
-  if (Histogram* h = internal_GetHistogramById(aId, aProcessType, SessionType::Session)) {
+  if (Histogram* h = internal_GetHistogramById(aId, aProcessType)) {
     internal_HistogramAdd(*h, aId, aSample, aProcessType);
   } else {
     NS_WARNING("Failed GetHistogramById for CHILD");
   }
-
-#if !defined(MOZ_WIDGET_ANDROID)
-  if (Histogram* h = internal_GetHistogramById(aId, aProcessType, SessionType::Subsession)) {
-    internal_HistogramAdd(*h, aId, aSample, aProcessType);
-  } else {
-    NS_WARNING("Failed GetHistogramById for CHILD");
-  }
-#endif
 }
 
 void
 internal_AccumulateChildKeyed(ProcessID aProcessType, HistogramID aId,
                               const nsCString& aKey, uint32_t aSample)
 {
   if (!gInitDone || !internal_CanRecordBase()) {
     return;
   }
 
   KeyedHistogram* keyed = internal_GetKeyedHistogramById(aId, aProcessType);
   MOZ_ASSERT(keyed);
   keyed->Add(aKey, aSample, aProcessType);
 }
 
 void
-internal_ClearHistogram(HistogramID id, bool onlySubsession)
+internal_ClearHistogram(HistogramID id)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   if (!XRE_IsParentProcess()) {
     return;
   }
 
   // Handle keyed histograms.
   if (gHistogramInfos[id].keyed) {
     for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
       KeyedHistogram* kh = internal_GetKeyedHistogramById(id, static_cast<ProcessID>(process), /* instantiate = */ false);
       if (kh) {
-        kh->Clear(onlySubsession);
+        kh->Clear();
       }
     }
   }
 
-  // Handle plain histograms.
-  // Define the session types we want to clear.
-  nsTArray<SessionType> sessionTypes;
-  if (!onlySubsession) {
-    sessionTypes.AppendElement(SessionType::Session);
-  }
-#if !defined(MOZ_WIDGET_ANDROID)
-  sessionTypes.AppendElement(SessionType::Subsession);
-#endif
-
   // Now reset the histograms instances for all processes.
-  for (SessionType sessionType : sessionTypes) {
-    for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
-      internal_ClearHistogramById(id,
-                                  static_cast<ProcessID>(process),
-                                  sessionType);
-    }
+  for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
+    internal_ClearHistogramById(id, static_cast<ProcessID>(process));
   }
 }
 
 } // namespace
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
@@ -1319,19 +1218,19 @@ internal_JSHistogram_Snapshot(JSContext 
 
   Histogram* h = nullptr;
   Histogram::SampleSet ss;
   {
     StaticMutexAutoLock locker(gTelemetryHistogramMutex);
     MOZ_ASSERT(internal_IsHistogramEnumId(id));
 
     // This is not good standard behavior given that we have histogram instances
-    // covering multiple processes and two session types.
+    // covering multiple processes.
     // However, changing this requires some broader changes to callers.
-    h = internal_GetHistogramById(id, ProcessID::Parent, SessionType::Session);
+    h = internal_GetHistogramById(id, ProcessID::Parent);
     // Take a snapshot of Histogram::SampleSet here, protected by the lock,
     // and then, outside of the lock protection, mirror it to a JS structure
     MOZ_ASSERT(h);
     h->SnapshotSample(&ss);
   }
 
   JS::Rooted<JSObject*> snapshot(cx, JS_NewPlainObject(cx));
   if (!snapshot) {
@@ -1363,38 +1262,26 @@ internal_JSHistogram_Clear(JSContext *cx
     JS_ReportErrorASCII(cx, "Wrong JS class, expected JSHistogram class");
     return false;
   }
 
   JSObject* obj = &args.thisv().toObject();
   JSHistogramData* data = static_cast<JSHistogramData*>(JS_GetPrivate(obj));
   MOZ_ASSERT(data);
 
-  bool onlySubsession = false;
   // This function should always return |undefined| and never fail but
   // rather report failures using the console.
   args.rval().setUndefined();
 
-#if !defined(MOZ_WIDGET_ANDROID)
-  if (args.length() >= 1) {
-    if (!args[0].isBoolean()) {
-      JS_ReportErrorASCII(cx, "Not a boolean");
-      return false;
-    }
-
-    onlySubsession = JS::ToBoolean(args[0]);
-  }
-#endif
-
   HistogramID id = data->histogramId;
   {
     StaticMutexAutoLock locker(gTelemetryHistogramMutex);
 
     MOZ_ASSERT(internal_IsHistogramEnumId(id));
-    internal_ClearHistogram(id, onlySubsession);
+    internal_ClearHistogram(id);
   }
 
   return true;
 }
 
 // NOTE: Runs without protection from |gTelemetryHistogramMutex|.
 // See comment at the top of this section.
 nsresult
@@ -1445,18 +1332,16 @@ internal_JSHistogram_finalize(JSFreeOp*,
 // PRIVATE: JSKeyedHistogram_* functions
 
 // NOTE: the functions in this section:
 //
 //   internal_KeyedHistogram_SnapshotImpl
 //   internal_JSKeyedHistogram_Add
 //   internal_JSKeyedHistogram_Keys
 //   internal_JSKeyedHistogram_Snapshot
-//   internal_JSKeyedHistogram_SubsessionSnapshot
-//   internal_JSKeyedHistogram_SnapshotSubsessionAndClear
 //   internal_JSKeyedHistogram_Clear
 //   internal_WrapAndReturnKeyedHistogram
 //
 // Same comments as above, at the JSHistogram_* section, regarding
 // deadlock avoidance, apply.
 
 namespace {
 
@@ -1476,17 +1361,17 @@ static const JSClass sJSKeyedHistogramCl
   "JSKeyedHistogram",  /* name */
   JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,  /* flags */
   &sJSKeyedHistogramClassOps
 };
 
 bool
 internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
                                      JS::Value *vp,
-                                     bool subsession, bool clearSubsession)
+                                     bool clearSubsession)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
 
   if (!args.thisv().isObject() ||
       JS_GetClass(&args.thisv().toObject()) != &sJSKeyedHistogramClass) {
     JS_ReportErrorASCII(cx, "Wrong JS class, expected JSKeyedHistogram class");
     return false;
   }
@@ -1497,48 +1382,48 @@ internal_KeyedHistogram_SnapshotImpl(JSC
   HistogramID id = data->histogramId;
   MOZ_ASSERT(internal_IsHistogramEnumId(id));
 
   // This function should always return |undefined| and never fail but
   // rather report failures using the console.
   args.rval().setUndefined();
 
   // This is not good standard behavior given that we have histogram instances
-  // covering multiple processes and two session types.
+  // covering multiple processes.
   // However, changing this requires some broader changes to callers.
   KeyedHistogram* keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ true);
   if (!keyed) {
     JS_ReportErrorASCII(cx, "Failed to look up keyed histogram");
     return false;
   }
 
   if (args.length() == 0) {
     JS::RootedObject snapshot(cx, JS_NewPlainObject(cx));
     if (!snapshot) {
       JS_ReportErrorASCII(cx, "Failed to create object");
       return false;
     }
 
-    if (!NS_SUCCEEDED(keyed->GetJSSnapshot(cx, snapshot, subsession, clearSubsession))) {
+    if (!NS_SUCCEEDED(keyed->GetJSSnapshot(cx, snapshot, clearSubsession))) {
       JS_ReportErrorASCII(cx, "Failed to reflect keyed histograms");
       return false;
     }
 
     args.rval().setObject(*snapshot);
     return true;
   }
 
   nsAutoJSString key;
   if (!args[0].isString() || !key.init(cx, args[0])) {
     JS_ReportErrorASCII(cx, "Not a string");
     return false;
   }
 
   Histogram* h = nullptr;
-  nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h, subsession);
+  nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h);
   if (NS_FAILED(rv)) {
     JS_ReportErrorASCII(cx, "Failed to get histogram");
     return false;
   }
 
   JS::RootedObject snapshot(cx, JS_NewPlainObject(cx));
   if (!snapshot) {
     return false;
@@ -1657,58 +1542,34 @@ internal_JSKeyedHistogram_Keys(JSContext
   HistogramID id = data->histogramId;
 
   KeyedHistogram* keyed = nullptr;
   {
     StaticMutexAutoLock locker(gTelemetryHistogramMutex);
     MOZ_ASSERT(internal_IsHistogramEnumId(id));
 
     // This is not good standard behavior given that we have histogram instances
-    // covering multiple processes and two session types.
+    // covering multiple processes.
     // However, changing this requires some broader changes to callers.
     keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent);
   }
 
   MOZ_ASSERT(keyed);
   if (!keyed) {
     return false;
   }
 
   return NS_SUCCEEDED(keyed->GetJSKeys(cx, args));
 }
 
 bool
 internal_JSKeyedHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
 {
-  return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, false, false);
-}
-
-#if !defined(MOZ_WIDGET_ANDROID)
-bool
-internal_JSKeyedHistogram_SubsessionSnapshot(JSContext *cx,
-                                             unsigned argc, JS::Value *vp)
-{
-  return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, true, false);
+  return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, false);
 }
-#endif
-
-#if !defined(MOZ_WIDGET_ANDROID)
-bool
-internal_JSKeyedHistogram_SnapshotSubsessionAndClear(JSContext *cx,
-                                                     unsigned argc,
-                                                     JS::Value *vp)
-{
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  if (args.length() != 0) {
-    JS_ReportErrorASCII(cx, "No key arguments supported for snapshotSubsessionAndClear");
-  }
-
-  return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, true, true);
-}
-#endif
 
 bool
 internal_JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
 
   if (!args.thisv().isObject() ||
       JS_GetClass(&args.thisv().toObject()) != &sJSKeyedHistogramClass) {
@@ -1720,42 +1581,31 @@ internal_JSKeyedHistogram_Clear(JSContex
   JSHistogramData* data = static_cast<JSHistogramData*>(JS_GetPrivate(obj));
   MOZ_ASSERT(data);
   HistogramID id = data->histogramId;
 
   // This function should always return |undefined| and never fail but
   // rather report failures using the console.
   args.rval().setUndefined();
 
-  bool onlySubsession = false;
-  #if !defined(MOZ_WIDGET_ANDROID)
-    if (args.length() >= 1) {
-      if (!(args[0].isNumber() || args[0].isBoolean())) {
-        JS_ReportErrorASCII(cx, "Not a boolean");
-        return false;
-      }
-      onlySubsession = JS::ToBoolean(args[0]);
-    }
-  #endif
-
   KeyedHistogram* keyed = nullptr;
   {
     MOZ_ASSERT(internal_IsHistogramEnumId(id));
     StaticMutexAutoLock locker(gTelemetryHistogramMutex);
 
     // This is not good standard behavior given that we have histogram instances
-    // covering multiple processes and two session types.
+    // covering multiple processes.
     // However, changing this requires some broader changes to callers.
     keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ false);
 
     if (!keyed) {
       return true;
     }
 
-    keyed->Clear(onlySubsession);
+    keyed->Clear();
   }
 
   return true;
 }
 
 // NOTE: Runs without protection from |gTelemetryHistogramMutex|.
 // See comment at the top of this section.
 nsresult
@@ -1765,22 +1615,16 @@ internal_WrapAndReturnKeyedHistogram(His
   JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &sJSKeyedHistogramClass));
   if (!obj)
     return NS_ERROR_FAILURE;
   // The 6 functions that are wrapped up here are eventually called
   // by the same thread that runs this function.
   if (!(JS_DefineFunction(cx, obj, "add", internal_JSKeyedHistogram_Add, 2, 0)
         && JS_DefineFunction(cx, obj, "snapshot",
                              internal_JSKeyedHistogram_Snapshot, 1, 0)
-#if !defined(MOZ_WIDGET_ANDROID)
-        && JS_DefineFunction(cx, obj, "subsessionSnapshot",
-                             internal_JSKeyedHistogram_SubsessionSnapshot, 1, 0)
-        && JS_DefineFunction(cx, obj, "snapshotSubsessionAndClear",
-                             internal_JSKeyedHistogram_SnapshotSubsessionAndClear, 0, 0)
-#endif
         && JS_DefineFunction(cx, obj, "keys",
                              internal_JSKeyedHistogram_Keys, 0, 0)
         && JS_DefineFunction(cx, obj, "clear",
                              internal_JSKeyedHistogram_Clear, 0, 0))) {
     return NS_ERROR_FAILURE;
   }
 
   JSHistogramData* data = new JSHistogramData{id};
@@ -1827,17 +1671,17 @@ void TelemetryHistogram::InitializeGloba
   MOZ_ASSERT(!gInitDone, "TelemetryHistogram::InitializeGlobalState "
              "may only be called once");
 
   gCanRecordBase = canRecordBase;
   gCanRecordExtended = canRecordExtended;
 
   if (XRE_IsParentProcess()) {
     gHistogramStorage =
-      new Histogram*[HistogramCount * size_t(ProcessID::Count) * size_t(SessionType::Count)] {};
+      new Histogram*[HistogramCount * size_t(ProcessID::Count)] {};
     gKeyedHistogramStorage =
       new KeyedHistogram*[HistogramCount * size_t(ProcessID::Count)] {};
   }
 
   // gNameToHistogramIDMap should have been pre-sized correctly at the
   // declaration point further up in this file.
 
   // Populate the static histogram name->id cache.
@@ -1889,17 +1733,17 @@ void TelemetryHistogram::DeInitializeGlo
   StaticMutexAutoLock locker(gTelemetryHistogramMutex);
   gCanRecordBase = false;
   gCanRecordExtended = false;
   gNameToHistogramIDMap.Clear();
   gInitDone = false;
 
   // FactoryGet `new`s Histograms for us, but requires us to manually delete.
   if (XRE_IsParentProcess()) {
-    for (size_t i = 0; i < HistogramCount * size_t(ProcessID::Count) * size_t(SessionType::Count); ++i) {
+    for (size_t i = 0; i < HistogramCount * size_t(ProcessID::Count); ++i) {
       if (i < HistogramCount * size_t(ProcessID::Count)) {
         delete gKeyedHistogramStorage[i];
       }
       if (gHistogramStorage[i] != gExpiredHistogram) {
         delete gHistogramStorage[i];
       }
     }
     delete[] gHistogramStorage;
@@ -2282,41 +2126,32 @@ TelemetryHistogram::GetHistogramName(His
   const HistogramInfo& h = gHistogramInfos[id];
   return h.name();
 }
 
 nsresult
 TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
                                              JS::MutableHandleValue aResult,
                                              unsigned int aDataset,
-                                             bool aSubsession,
                                              bool aClearSubsession)
 {
-#if defined(MOZ_WIDGET_ANDROID)
-  if (aSubsession) {
-    return NS_OK;
-  }
-#endif
-
   // Runs without protection from |gTelemetryHistogramMutex|
   JS::Rooted<JSObject*> root_obj(aCx, JS_NewPlainObject(aCx));
   if (!root_obj) {
     return NS_ERROR_FAILURE;
   }
   aResult.setObject(*root_obj);
 
   // 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();
   }
 
-  SessionType sessionType = SessionType(aSubsession);
-
   // Struct used to keep information about the histograms for which a
   // snapshot should be created
   struct MOZ_NON_MEMMOVABLE HistogramProcessInfo {
     Histogram* h;
     Histogram::SampleSet ss;
     size_t index;
   };
 
@@ -2346,33 +2181,30 @@ TelemetryHistogram::CreateHistogramSnaps
 
         if (!IsInDataset(info.dataset, aDataset)) {
           continue;
         }
 
         bool shouldInstantiate =
           info.histogramType == nsITelemetry::HISTOGRAM_FLAG;
         Histogram* h = internal_GetHistogramById(id, ProcessID(process),
-                                                 sessionType,
                                                  shouldInstantiate);
         if (!h || internal_IsExpired(h) || !internal_ShouldReflectHistogram(h, id)) {
           continue;
         }
 
         Histogram::SampleSet ss;
         h->SnapshotSample(&ss);
         if (!hArray.emplaceBack(HistogramProcessInfo{h, ss, i})) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
-#if !defined(MOZ_WIDGET_ANDROID)
-        if ((sessionType == SessionType::Subsession) && aClearSubsession) {
+        if (aClearSubsession) {
           h->Clear();
         }
-#endif
       }
     }
   }
 
   // Make the JS calls on the stashed histograms for every process
   for (uint32_t process = 0; process < processHistArray.length(); ++process) {
     JS::Rooted<JSObject*> processObject(aCx, JS_NewPlainObject(aCx));
     if (!processObject) {
@@ -2412,24 +2244,18 @@ TelemetryHistogram::CreateHistogramSnaps
   }
   return NS_OK;
 }
 
 nsresult
 TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
                                                JS::MutableHandleValue aResult,
                                                unsigned int aDataset,
-                                               bool aSubsession,
                                                bool aClearSubsession)
 {
-#if defined(MOZ_WIDGET_ANDROID)
-  if (aSubsession) {
-    return NS_OK;
-  }
-#endif
   // Runs without protection from |gTelemetryHistogramMutex|
   JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
   aResult.setObject(*obj);
 
   // Include the GPU process in histogram snapshots only if we actually tried
@@ -2470,18 +2296,17 @@ TelemetryHistogram::GetKeyedHistogramSna
         continue;
       }
 
       JS::RootedObject snapshot(aCx, JS_NewPlainObject(aCx));
       if (!snapshot) {
         return NS_ERROR_FAILURE;
       }
 
-      if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aSubsession,
-                                             aClearSubsession))) {
+      if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aClearSubsession))) {
         return NS_ERROR_FAILURE;
       }
 
       if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
                              snapshot, JSPROP_ENUMERATE)) {
         return NS_ERROR_FAILURE;
       }
     }
--- a/toolkit/components/telemetry/TelemetryHistogram.h
+++ b/toolkit/components/telemetry/TelemetryHistogram.h
@@ -60,21 +60,21 @@ nsresult
 GetKeyedHistogramById(const nsACString &name, JSContext *cx,
                       JS::MutableHandle<JS::Value> ret);
 
 const char*
 GetHistogramName(mozilla::Telemetry::HistogramID id);
 
 nsresult
 CreateHistogramSnapshots(JSContext* aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
-                         bool aSubsession, bool aClearSubsession);
+                         bool aClearSubsession);
 
 nsresult
 GetKeyedHistogramSnapshots(JSContext *aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
-                           bool aSubsession, bool aClearSubsession);
+                           bool aClearSubsession);
 
 size_t
 GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 size_t
 GetHistogramSizesofIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 } // namespace TelemetryHistogram
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -867,34 +867,34 @@ var Impl = {
    * Get the type of the dataset that needs to be collected, based on the preferences.
    * @return {Integer} A value from nsITelemetry.DATASET_*.
    */
   getDatasetType() {
     return Telemetry.canRecordExtended ? Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN
                                        : Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
   },
 
-  getHistograms: function getHistograms(subsession, clearSubsession) {
-    let hls = Telemetry.snapshotHistograms(this.getDatasetType(), subsession, clearSubsession);
+  getHistograms: function getHistograms(clearSubsession) {
+    let hls = Telemetry.snapshotHistograms(this.getDatasetType(), clearSubsession);
     let ret = {};
 
     for (let [process, histograms] of Object.entries(hls)) {
       ret[process] = {};
       for (let [name, value] of Object.entries(histograms)) {
         if (this._testing || !name.startsWith("TELEMETRY_TEST_")) {
           ret[process][name] = this.packHistogram(value);
         }
       }
     }
 
     return ret;
   },
 
-  getKeyedHistograms(subsession, clearSubsession) {
-    let khs = Telemetry.snapshotKeyedHistograms(this.getDatasetType(), subsession, clearSubsession);
+  getKeyedHistograms(clearSubsession) {
+    let khs = Telemetry.snapshotKeyedHistograms(this.getDatasetType(), clearSubsession);
     let ret = {};
 
     for (let [process, histograms] of Object.entries(khs)) {
       ret[process] = {};
       for (let [name, value] of Object.entries(histograms)) {
         if (this._testing || !name.startsWith("TELEMETRY_TEST_")) {
           let keys = Object.keys(value);
           if (keys.length == 0) {
@@ -1217,18 +1217,18 @@ var Impl = {
     }
 
     if (Utils.isContentProcess) {
       return payloadObj;
     }
 
     // Additional payload for chrome process.
     let measurements = {
-      histograms: protect(() => this.getHistograms(isSubsession, clearSubsession), {}),
-      keyedHistograms: protect(() => this.getKeyedHistograms(isSubsession, clearSubsession), {}),
+      histograms: protect(() => this.getHistograms(clearSubsession), {}),
+      keyedHistograms: protect(() => this.getKeyedHistograms(clearSubsession), {}),
       scalars: protect(() => this.getScalars(isSubsession, clearSubsession), {}),
       keyedScalars: protect(() => this.getScalars(isSubsession, clearSubsession, true), {}),
       events: protect(() => this.getEvents(isSubsession, clearSubsession)),
     };
 
     let measurementsContainGPU = Object
       .keys(measurements)
       .some(key => "gpu" in measurements[key]);
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -61,21 +61,20 @@ interface nsITelemetry : nsISupports
    *   max - maximum bucket size
    *   histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, HISTOGRAM_BOOLEAN,
    *                    HISTOGRAM_FLAG, HISTOGRAM_COUNT, or HISTOGRAM_CATEGORICAL
    *   counts - array representing contents of the buckets in the histogram
    *   ranges - array with calculated bucket sizes
    *   sum - sum of the bucket contents
    *
    * @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN.
-   * @param aSubsession Whether to return the internally-duplicated subsession histograms
-   * @param aClear Whether to clear out the subsession histograms after snapshotting (only works if aSubsession is true)
+   * @param aClear Whether to clear out the histograms after snapshotting
    */
   [implicit_jscontext]
-  jsval snapshotHistograms(in uint32_t aDataset, in boolean aSubsession, in boolean aClear);
+  jsval snapshotHistograms(in uint32_t aDataset, in boolean aClear);
 
   /**
    * The amount of time, in milliseconds, that the last session took
    * to shutdown.  Reads as 0 to indicate failure.
    */
   readonly attribute uint32_t lastShutdownDuration;
 
   /**
@@ -228,21 +227,20 @@ interface nsITelemetry : nsISupports
   jsval getHistogramById(in ACString id);
 
   /**
    * Serializes the keyed histograms from the given dataset to a JSON-style object.
    * The returned structure looks like:
    *   { process1: {name1: {histogramData1}, name2:{histogramData2}...}}
    *
    * @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN.
-   * @param aSubsession Whether to return the internally-duplicated subsession keyed histograms
-   * @param aClear Whether to clear out the subsession keyed histograms after snapshotting (only works if aSubsession is true)
+   * @param aClear Whether to clear out the keyed histograms after snapshotting
    */
   [implicit_jscontext]
-  jsval snapshotKeyedHistograms(in uint32_t aDataset, in boolean aSubsession, in boolean aClear);
+  jsval snapshotKeyedHistograms(in uint32_t aDataset, in boolean aClear);
 
   /**
    * Create and return a histogram registered in TelemetryHistograms.h.
    *
    * @param id - unique identifier from TelemetryHistograms.h
    * The returned object has the following functions:
    *   add(string key, [optional] int) - Add an int value to the histogram for that key. If no histogram for that key exists yet, it is created.
    *   snapshot([optional] string key) - If key is provided, returns a snapshot for the histogram with that key or null. If key is not provided, returns the snapshots of all the registered keys in the form {key1: snapshot1, key2: snapshot2, ...}.