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

--HG--
extra : rebase_source : 50bb218c9fb9a04c8d60d6300e4e9e67544232c0
This commit is contained in:
Jan-Erik Rediger 2018-05-02 15:43:02 +02:00
Родитель 92baffe42e
Коммит 871a4b2e0d
5 изменённых файлов: 62 добавлений и 251 удалений

Просмотреть файл

@ -577,32 +577,20 @@ TelemetryImpl::SetHistogramRecordingEnabled(const nsACString &id, bool aEnabled)
} }
NS_IMETHODIMP NS_IMETHODIMP
TelemetryImpl::SnapshotHistograms(unsigned int aDataset, bool aSubsession, TelemetryImpl::SnapshotHistograms(unsigned int aDataset,
bool aClearHistograms, JSContext* aCx, bool aClearHistograms, JSContext* aCx,
JS::MutableHandleValue aResult) JS::MutableHandleValue aResult)
{ {
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
return TelemetryHistogram::CreateHistogramSnapshots(aCx, aResult, aDataset, return TelemetryHistogram::CreateHistogramSnapshots(aCx, aResult, aDataset,
aSubsession,
aClearHistograms); aClearHistograms);
} }
NS_IMETHODIMP NS_IMETHODIMP
TelemetryImpl::SnapshotKeyedHistograms(unsigned int aDataset, bool aSubsession, TelemetryImpl::SnapshotKeyedHistograms(unsigned int aDataset,
bool aClearHistograms, JSContext* aCx, bool aClearHistograms, JSContext* aCx,
JS::MutableHandleValue aResult) JS::MutableHandleValue aResult)
{ {
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
return TelemetryHistogram::GetKeyedHistogramSnapshots(aCx, aResult, aDataset, return TelemetryHistogram::GetKeyedHistogramSnapshots(aCx, aResult, aDataset,
aSubsession,
aClearHistograms); aClearHistograms);
} }

Просмотреть файл

@ -144,25 +144,19 @@ enum reflectStatus {
REFLECT_FAILURE REFLECT_FAILURE
}; };
enum class SessionType {
Session = 0,
Subsession = 1,
Count,
};
class KeyedHistogram { class KeyedHistogram {
public: public:
KeyedHistogram(HistogramID id, const HistogramInfo& info); KeyedHistogram(HistogramID id, const HistogramInfo& info);
~KeyedHistogram(); ~KeyedHistogram();
nsresult GetHistogram(const nsCString& name, Histogram** histogram, bool subsession); nsresult GetHistogram(const nsCString& name, Histogram** histogram);
Histogram* GetHistogram(const nsCString& name, bool subsession); Histogram* GetHistogram(const nsCString& name);
uint32_t GetHistogramType() const { return mHistogramInfo.histogramType; } uint32_t GetHistogramType() const { return mHistogramInfo.histogramType; }
nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args); nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args);
nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj,
bool subsession, bool clearSubsession); bool clearSubsession);
nsresult Add(const nsCString& key, uint32_t aSample, ProcessID aProcessType); nsresult Add(const nsCString& key, uint32_t aSample, ProcessID aProcessType);
void Clear(bool subsession); void Clear();
HistogramID GetHistogramID() const { return mId; } HistogramID GetHistogramID() const { return mId; }
@ -170,9 +164,6 @@ private:
typedef nsBaseHashtableET<nsCStringHashKey, Histogram*> KeyedHistogramEntry; typedef nsBaseHashtableET<nsCStringHashKey, Histogram*> KeyedHistogramEntry;
typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType; typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType;
KeyedHistogramMapType mHistogramMap; KeyedHistogramMapType mHistogramMap;
#if !defined(MOZ_WIDGET_ANDROID)
KeyedHistogramMapType mSubsessionMap;
#endif
static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry, static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry,
JSContext* cx, JSContext* cx,
@ -204,7 +195,6 @@ bool gCanRecordExtended = false;
// We use separate ones for plain and keyed histograms. // We use separate ones for plain and keyed histograms.
Histogram** gHistogramStorage; Histogram** gHistogramStorage;
// Keyed histograms internally map string keys to individual Histogram instances. // Keyed histograms internally map string keys to individual Histogram instances.
// KeyedHistogram keeps track of session & subsession histograms internally.
KeyedHistogram** gKeyedHistogramStorage; KeyedHistogram** gKeyedHistogramStorage;
// Cache of histogram name to a histogram id. // Cache of histogram name to a histogram id.
@ -256,37 +246,31 @@ size_t internal_KeyedHistogramStorageIndex(HistogramID aHistogramId,
} }
size_t internal_HistogramStorageIndex(HistogramID aHistogramId, size_t internal_HistogramStorageIndex(HistogramID aHistogramId,
ProcessID aProcessId, ProcessID aProcessId)
SessionType aSessionType)
{ {
static_assert( static_assert(
HistogramCount < HistogramCount <
std::numeric_limits<size_t>::max() / size_t(ProcessID::Count) / size_t(SessionType::Count), std::numeric_limits<size_t>::max() / size_t(ProcessID::Count),
"Too many histograms, processes, and session types to store in a 1D " "Too many histograms and processes to store in a 1D array.");
"array.");
return aHistogramId * size_t(ProcessID::Count) * size_t(SessionType::Count) + return aHistogramId * size_t(ProcessID::Count) + size_t(aProcessId);
size_t(aProcessId) * size_t(SessionType::Count) +
size_t(aSessionType);
} }
Histogram* internal_GetHistogramFromStorage(HistogramID aHistogramId, Histogram* internal_GetHistogramFromStorage(HistogramID aHistogramId,
ProcessID aProcessId, ProcessID aProcessId)
SessionType aSessionType)
{ {
size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId, aSessionType); size_t index = internal_HistogramStorageIndex(aHistogramId, aProcessId);
return gHistogramStorage[index]; return gHistogramStorage[index];
} }
void internal_SetHistogramInStorage(HistogramID aHistogramId, void internal_SetHistogramInStorage(HistogramID aHistogramId,
ProcessID aProcessId, ProcessID aProcessId,
SessionType aSessionType,
Histogram* aHistogram) Histogram* aHistogram)
{ {
MOZ_ASSERT(XRE_IsParentProcess(), MOZ_ASSERT(XRE_IsParentProcess(),
"Histograms are stored only in the parent process."); "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], MOZ_ASSERT(!gHistogramStorage[index],
"Mustn't overwrite storage without clearing it first."); "Mustn't overwrite storage without clearing it first.");
gHistogramStorage[index] = aHistogram; gHistogramStorage[index] = aHistogram;
@ -325,17 +309,13 @@ internal_IsHistogramEnumId(HistogramID aID)
// Look up a plain histogram by id. // Look up a plain histogram by id.
Histogram* Histogram*
internal_GetHistogramById(HistogramID histogramId, ProcessID processId, SessionType sessionType, internal_GetHistogramById(HistogramID histogramId, ProcessID processId, bool instantiate = true)
bool instantiate = true)
{ {
MOZ_ASSERT(internal_IsHistogramEnumId(histogramId)); MOZ_ASSERT(internal_IsHistogramEnumId(histogramId));
MOZ_ASSERT(!gHistogramInfos[histogramId].keyed); MOZ_ASSERT(!gHistogramInfos[histogramId].keyed);
MOZ_ASSERT(processId < ProcessID::Count); MOZ_ASSERT(processId < ProcessID::Count);
MOZ_ASSERT(sessionType < SessionType::Count);
Histogram* h = internal_GetHistogramFromStorage(histogramId, Histogram* h = internal_GetHistogramFromStorage(histogramId, processId);
processId,
sessionType);
if (h || !instantiate) { if (h || !instantiate) {
return h; return h;
} }
@ -344,7 +324,7 @@ internal_GetHistogramById(HistogramID histogramId, ProcessID processId, SessionT
const int bucketsOffset = gHistogramBucketLowerBoundIndex[histogramId]; const int bucketsOffset = gHistogramBucketLowerBoundIndex[histogramId];
h = internal_CreateHistogramInstance(info, bucketsOffset); h = internal_CreateHistogramInstance(info, bucketsOffset);
MOZ_ASSERT(h); MOZ_ASSERT(h);
internal_SetHistogramInStorage(histogramId, processId, sessionType, h); internal_SetHistogramInStorage(histogramId, processId, h);
return h; return h;
} }
@ -384,9 +364,9 @@ internal_GetHistogramIdByName(const nsACString& name, HistogramID* id)
// Clear a histogram from storage. // Clear a histogram from storage.
void 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) { if (gHistogramStorage[index] == gExpiredHistogram) {
// We keep gExpiredHistogram until TelemetryHistogram::DeInitializeGlobalState // We keep gExpiredHistogram until TelemetryHistogram::DeInitializeGlobalState
return; return;
@ -628,8 +608,6 @@ internal_HistogramAdd(Histogram& histogram,
value = INT_MAX; 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); histogram.Add(value);
return NS_OK; return NS_OK;
@ -734,9 +712,6 @@ namespace {
KeyedHistogram::KeyedHistogram(HistogramID id, const HistogramInfo& info) KeyedHistogram::KeyedHistogram(HistogramID id, const HistogramInfo& info)
: mHistogramMap() : mHistogramMap()
#if !defined(MOZ_WIDGET_ANDROID)
, mSubsessionMap()
#endif
, mId(id) , mId(id)
, mHistogramInfo(info) , mHistogramInfo(info)
{ {
@ -752,29 +727,12 @@ KeyedHistogram::~KeyedHistogram()
delete h; delete h;
} }
mHistogramMap.Clear(); 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 nsresult
KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram, KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram)
bool subsession)
{ {
#if !defined(MOZ_WIDGET_ANDROID) KeyedHistogramEntry* entry = mHistogramMap.GetEntry(key);
KeyedHistogramMapType& map = subsession ? mSubsessionMap : mHistogramMap;
#else
KeyedHistogramMapType& map = mHistogramMap;
#endif
KeyedHistogramEntry* entry = map.GetEntry(key);
if (entry) { if (entry) {
*histogram = entry->mData; *histogram = entry->mData;
return NS_OK; return NS_OK;
@ -789,7 +747,7 @@ KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram,
h->ClearFlags(Histogram::kUmaTargetedHistogramFlag); h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
*histogram = h; *histogram = h;
entry = map.PutEntry(key); entry = mHistogramMap.PutEntry(key);
if (MOZ_UNLIKELY(!entry)) { if (MOZ_UNLIKELY(!entry)) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -799,10 +757,10 @@ KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram,
} }
Histogram* Histogram*
KeyedHistogram::GetHistogram(const nsCString& key, bool subsession) KeyedHistogram::GetHistogram(const nsCString& key)
{ {
Histogram* h = nullptr; Histogram* h = nullptr;
if (NS_FAILED(GetHistogram(key, &h, subsession))) { if (NS_FAILED(GetHistogram(key, &h))) {
return nullptr; return nullptr;
} }
return h; return h;
@ -827,18 +785,11 @@ KeyedHistogram::Add(const nsCString& key, uint32_t sample,
return NS_OK; return NS_OK;
} }
Histogram* histogram = GetHistogram(key, false); Histogram* histogram = GetHistogram(key);
MOZ_ASSERT(histogram); MOZ_ASSERT(histogram);
if (!histogram) { if (!histogram) {
return NS_ERROR_FAILURE; 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`. // 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 // Clamp large values of `sample` to be INT_MAX so they continue to be treated
@ -851,32 +802,16 @@ KeyedHistogram::Add(const nsCString& key, uint32_t sample,
} }
histogram->Add(sample); histogram->Add(sample);
#if !defined(MOZ_WIDGET_ANDROID)
subsession->Add(sample);
#endif
return NS_OK; return NS_OK;
} }
void void
KeyedHistogram::Clear(bool onlySubsession) KeyedHistogram::Clear()
{ {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
if (!XRE_IsParentProcess()) { if (!XRE_IsParentProcess()) {
return; 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()) { for (auto iter = mHistogramMap.Iter(); !iter.Done(); iter.Next()) {
Histogram* h = iter.Get()->mData; Histogram* h = iter.Get()->mData;
@ -937,23 +872,15 @@ KeyedHistogram::ReflectKeyedHistogram(KeyedHistogramEntry* entry,
} }
nsresult nsresult
KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, bool clearSubsession)
bool subsession, bool clearSubsession)
{ {
#if !defined(MOZ_WIDGET_ANDROID) if (!mHistogramMap.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
KeyedHistogramMapType& map = subsession ? mSubsessionMap : mHistogramMap;
#else
KeyedHistogramMapType& map = mHistogramMap;
#endif
if (!map.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
#if !defined(MOZ_WIDGET_ANDROID) if (clearSubsession) {
if (subsession && clearSubsession) { Clear();
Clear(true);
} }
#endif
return NS_OK; return NS_OK;
} }
@ -1013,15 +940,9 @@ void internal_Accumulate(HistogramID aId, uint32_t aSample)
return; return;
} }
Histogram *h = internal_GetHistogramById(aId, ProcessID::Parent, SessionType::Session); Histogram *h = internal_GetHistogramById(aId, ProcessID::Parent);
MOZ_ASSERT(h); MOZ_ASSERT(h);
internal_HistogramAdd(*h, aId, aSample, ProcessID::Parent); 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 void
@ -1045,19 +966,11 @@ internal_AccumulateChild(ProcessID aProcessType, HistogramID aId, uint32_t aSamp
return; return;
} }
if (Histogram* h = internal_GetHistogramById(aId, aProcessType, SessionType::Session)) { if (Histogram* h = internal_GetHistogramById(aId, aProcessType)) {
internal_HistogramAdd(*h, aId, aSample, aProcessType); internal_HistogramAdd(*h, aId, aSample, aProcessType);
} else { } else {
NS_WARNING("Failed GetHistogramById for CHILD"); 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 void
@ -1074,7 +987,7 @@ internal_AccumulateChildKeyed(ProcessID aProcessType, HistogramID aId,
} }
void void
internal_ClearHistogram(HistogramID id, bool onlySubsession) internal_ClearHistogram(HistogramID id)
{ {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
if (!XRE_IsParentProcess()) { if (!XRE_IsParentProcess()) {
@ -1086,28 +999,14 @@ internal_ClearHistogram(HistogramID id, bool onlySubsession)
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) { for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
KeyedHistogram* kh = internal_GetKeyedHistogramById(id, static_cast<ProcessID>(process), /* instantiate = */ false); KeyedHistogram* kh = internal_GetKeyedHistogramById(id, static_cast<ProcessID>(process), /* instantiate = */ false);
if (kh) { 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. // 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) {
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) { internal_ClearHistogramById(id, static_cast<ProcessID>(process));
internal_ClearHistogramById(id,
static_cast<ProcessID>(process),
sessionType);
}
} }
} }
@ -1336,9 +1235,9 @@ internal_JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
MOZ_ASSERT(internal_IsHistogramEnumId(id)); MOZ_ASSERT(internal_IsHistogramEnumId(id));
// This is not good standard behavior given that we have histogram instances // 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. // 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, // Take a snapshot of Histogram::SampleSet here, protected by the lock,
// and then, outside of the lock protection, mirror it to a JS structure // and then, outside of the lock protection, mirror it to a JS structure
MOZ_ASSERT(h); MOZ_ASSERT(h);
@ -1380,28 +1279,16 @@ internal_JSHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
JSHistogramData* data = static_cast<JSHistogramData*>(JS_GetPrivate(obj)); JSHistogramData* data = static_cast<JSHistogramData*>(JS_GetPrivate(obj));
MOZ_ASSERT(data); MOZ_ASSERT(data);
bool onlySubsession = false;
// This function should always return |undefined| and never fail but // This function should always return |undefined| and never fail but
// rather report failures using the console. // rather report failures using the console.
args.rval().setUndefined(); 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; HistogramID id = data->histogramId;
{ {
StaticMutexAutoLock locker(gTelemetryHistogramMutex); StaticMutexAutoLock locker(gTelemetryHistogramMutex);
MOZ_ASSERT(internal_IsHistogramEnumId(id)); MOZ_ASSERT(internal_IsHistogramEnumId(id));
internal_ClearHistogram(id, onlySubsession); internal_ClearHistogram(id);
} }
return true; return true;
@ -1462,8 +1349,6 @@ internal_JSHistogram_finalize(JSFreeOp*, JSObject* obj)
// internal_JSKeyedHistogram_Add // internal_JSKeyedHistogram_Add
// internal_JSKeyedHistogram_Keys // internal_JSKeyedHistogram_Keys
// internal_JSKeyedHistogram_Snapshot // internal_JSKeyedHistogram_Snapshot
// internal_JSKeyedHistogram_SubsessionSnapshot
// internal_JSKeyedHistogram_SnapshotSubsessionAndClear
// internal_JSKeyedHistogram_Clear // internal_JSKeyedHistogram_Clear
// internal_WrapAndReturnKeyedHistogram // internal_WrapAndReturnKeyedHistogram
// //
@ -1493,7 +1378,7 @@ static const JSClass sJSKeyedHistogramClass = {
bool bool
internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc, internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
JS::Value *vp, JS::Value *vp,
bool subsession, bool clearSubsession) bool clearSubsession)
{ {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@ -1514,7 +1399,7 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
args.rval().setUndefined(); args.rval().setUndefined();
// This is not good standard behavior given that we have histogram instances // 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. // However, changing this requires some broader changes to callers.
KeyedHistogram* keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ true); KeyedHistogram* keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ true);
if (!keyed) { if (!keyed) {
@ -1529,7 +1414,7 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
return false; 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"); JS_ReportErrorASCII(cx, "Failed to reflect keyed histograms");
return false; return false;
} }
@ -1545,7 +1430,7 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
} }
Histogram* h = nullptr; Histogram* h = nullptr;
nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h, subsession); nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
JS_ReportErrorASCII(cx, "Failed to get histogram"); JS_ReportErrorASCII(cx, "Failed to get histogram");
return false; return false;
@ -1653,7 +1538,7 @@ internal_JSKeyedHistogram_Keys(JSContext *cx, unsigned argc, JS::Value *vp)
MOZ_ASSERT(internal_IsHistogramEnumId(id)); MOZ_ASSERT(internal_IsHistogramEnumId(id));
// This is not good standard behavior given that we have histogram instances // 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. // However, changing this requires some broader changes to callers.
keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent); keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent);
} }
@ -1669,33 +1554,9 @@ internal_JSKeyedHistogram_Keys(JSContext *cx, unsigned argc, JS::Value *vp)
bool bool
internal_JSKeyedHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp) internal_JSKeyedHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
{ {
return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, false, false); return internal_KeyedHistogram_SnapshotImpl(cx, argc, vp, 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);
}
#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 bool
internal_JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp) internal_JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
{ {
@ -1716,24 +1577,13 @@ internal_JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
// rather report failures using the console. // rather report failures using the console.
args.rval().setUndefined(); 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; KeyedHistogram* keyed = nullptr;
{ {
MOZ_ASSERT(internal_IsHistogramEnumId(id)); MOZ_ASSERT(internal_IsHistogramEnumId(id));
StaticMutexAutoLock locker(gTelemetryHistogramMutex); StaticMutexAutoLock locker(gTelemetryHistogramMutex);
// This is not good standard behavior given that we have histogram instances // 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. // However, changing this requires some broader changes to callers.
keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ false); keyed = internal_GetKeyedHistogramById(id, ProcessID::Parent, /* instantiate = */ false);
@ -1741,7 +1591,7 @@ internal_JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
return true; return true;
} }
keyed->Clear(onlySubsession); keyed->Clear();
} }
return true; return true;
@ -1761,12 +1611,6 @@ internal_WrapAndReturnKeyedHistogram(HistogramID id, JSContext *cx,
if (!(JS_DefineFunction(cx, obj, "add", internal_JSKeyedHistogram_Add, 2, 0) if (!(JS_DefineFunction(cx, obj, "add", internal_JSKeyedHistogram_Add, 2, 0)
&& JS_DefineFunction(cx, obj, "snapshot", && JS_DefineFunction(cx, obj, "snapshot",
internal_JSKeyedHistogram_Snapshot, 1, 0) 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", && JS_DefineFunction(cx, obj, "keys",
internal_JSKeyedHistogram_Keys, 0, 0) internal_JSKeyedHistogram_Keys, 0, 0)
&& JS_DefineFunction(cx, obj, "clear", && JS_DefineFunction(cx, obj, "clear",
@ -1823,7 +1667,7 @@ void TelemetryHistogram::InitializeGlobalState(bool canRecordBase,
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
gHistogramStorage = gHistogramStorage =
new Histogram*[HistogramCount * size_t(ProcessID::Count) * size_t(SessionType::Count)] {}; new Histogram*[HistogramCount * size_t(ProcessID::Count)] {};
gKeyedHistogramStorage = gKeyedHistogramStorage =
new KeyedHistogram*[HistogramCount * size_t(ProcessID::Count)] {}; new KeyedHistogram*[HistogramCount * size_t(ProcessID::Count)] {};
} }
@ -1885,7 +1729,7 @@ void TelemetryHistogram::DeInitializeGlobalState()
// FactoryGet `new`s Histograms for us, but requires us to manually delete. // FactoryGet `new`s Histograms for us, but requires us to manually delete.
if (XRE_IsParentProcess()) { 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)) { if (i < HistogramCount * size_t(ProcessID::Count)) {
delete gKeyedHistogramStorage[i]; delete gKeyedHistogramStorage[i];
} }
@ -2278,15 +2122,8 @@ nsresult
TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx, TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
JS::MutableHandleValue aResult, JS::MutableHandleValue aResult,
unsigned int aDataset, unsigned int aDataset,
bool aSubsession,
bool aClearSubsession) bool aClearSubsession)
{ {
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
// Runs without protection from |gTelemetryHistogramMutex| // Runs without protection from |gTelemetryHistogramMutex|
JS::Rooted<JSObject*> root_obj(aCx, JS_NewPlainObject(aCx)); JS::Rooted<JSObject*> root_obj(aCx, JS_NewPlainObject(aCx));
if (!root_obj) { if (!root_obj) {
@ -2301,8 +2138,6 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
includeGPUProcess = gpm->AttemptedGPUProcess(); includeGPUProcess = gpm->AttemptedGPUProcess();
} }
SessionType sessionType = SessionType(aSubsession);
// Struct used to keep information about the histograms for which a // Struct used to keep information about the histograms for which a
// snapshot should be created // snapshot should be created
struct MOZ_NON_MEMMOVABLE HistogramProcessInfo { struct MOZ_NON_MEMMOVABLE HistogramProcessInfo {
@ -2342,7 +2177,6 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
bool shouldInstantiate = bool shouldInstantiate =
info.histogramType == nsITelemetry::HISTOGRAM_FLAG; info.histogramType == nsITelemetry::HISTOGRAM_FLAG;
Histogram* h = internal_GetHistogramById(id, ProcessID(process), Histogram* h = internal_GetHistogramById(id, ProcessID(process),
sessionType,
shouldInstantiate); shouldInstantiate);
if (!h || internal_IsExpired(h) || !internal_ShouldReflectHistogram(h, id)) { if (!h || internal_IsExpired(h) || !internal_ShouldReflectHistogram(h, id)) {
continue; continue;
@ -2354,11 +2188,9 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
#if !defined(MOZ_WIDGET_ANDROID) if (aClearSubsession) {
if ((sessionType == SessionType::Subsession) && aClearSubsession) {
h->Clear(); h->Clear();
} }
#endif
} }
} }
} }
@ -2408,14 +2240,8 @@ nsresult
TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx, TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
JS::MutableHandleValue aResult, JS::MutableHandleValue aResult,
unsigned int aDataset, unsigned int aDataset,
bool aSubsession,
bool aClearSubsession) bool aClearSubsession)
{ {
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
// Runs without protection from |gTelemetryHistogramMutex| // Runs without protection from |gTelemetryHistogramMutex|
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx)); JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
if (!obj) { if (!obj) {
@ -2466,8 +2292,7 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aSubsession, if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aClearSubsession))) {
aClearSubsession))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

Просмотреть файл

@ -65,11 +65,11 @@ GetHistogramName(mozilla::Telemetry::HistogramID id);
nsresult nsresult
CreateHistogramSnapshots(JSContext* aCx, JS::MutableHandleValue aResult, unsigned int aDataset, CreateHistogramSnapshots(JSContext* aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
bool aSubsession, bool aClearSubsession); bool aClearSubsession);
nsresult nsresult
GetKeyedHistogramSnapshots(JSContext *aCx, JS::MutableHandleValue aResult, unsigned int aDataset, GetKeyedHistogramSnapshots(JSContext *aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
bool aSubsession, bool aClearSubsession); bool aClearSubsession);
size_t size_t
GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);

Просмотреть файл

@ -871,8 +871,8 @@ var Impl = {
: Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT; : Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
}, },
getHistograms: function getHistograms(subsession, clearSubsession) { getHistograms: function getHistograms(clearSubsession) {
let hls = Telemetry.snapshotHistograms(this.getDatasetType(), subsession, clearSubsession); let hls = Telemetry.snapshotHistograms(this.getDatasetType(), clearSubsession);
let ret = {}; let ret = {};
for (let [process, histograms] of Object.entries(hls)) { for (let [process, histograms] of Object.entries(hls)) {
@ -887,8 +887,8 @@ var Impl = {
return ret; return ret;
}, },
getKeyedHistograms(subsession, clearSubsession) { getKeyedHistograms(clearSubsession) {
let khs = Telemetry.snapshotKeyedHistograms(this.getDatasetType(), subsession, clearSubsession); let khs = Telemetry.snapshotKeyedHistograms(this.getDatasetType(), clearSubsession);
let ret = {}; let ret = {};
for (let [process, histograms] of Object.entries(khs)) { for (let [process, histograms] of Object.entries(khs)) {
@ -1221,8 +1221,8 @@ var Impl = {
// Additional payload for chrome process. // Additional payload for chrome process.
let measurements = { let measurements = {
histograms: protect(() => this.getHistograms(isSubsession, clearSubsession), {}), histograms: protect(() => this.getHistograms(clearSubsession), {}),
keyedHistograms: protect(() => this.getKeyedHistograms(isSubsession, clearSubsession), {}), keyedHistograms: protect(() => this.getKeyedHistograms(clearSubsession), {}),
scalars: protect(() => this.getScalars(isSubsession, clearSubsession), {}), scalars: protect(() => this.getScalars(isSubsession, clearSubsession), {}),
keyedScalars: protect(() => this.getScalars(isSubsession, clearSubsession, true), {}), keyedScalars: protect(() => this.getScalars(isSubsession, clearSubsession, true), {}),
events: protect(() => this.getEvents(isSubsession, clearSubsession)), events: protect(() => this.getEvents(isSubsession, clearSubsession)),

Просмотреть файл

@ -66,11 +66,10 @@ interface nsITelemetry : nsISupports
* sum - sum of the bucket contents * sum - sum of the bucket contents
* *
* @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN. * @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 histograms after snapshotting
* @param aClear Whether to clear out the subsession histograms after snapshotting (only works if aSubsession is true)
*/ */
[implicit_jscontext] [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 * The amount of time, in milliseconds, that the last session took
@ -233,11 +232,10 @@ interface nsITelemetry : nsISupports
* { process1: {name1: {histogramData1}, name2:{histogramData2}...}} * { process1: {name1: {histogramData1}, name2:{histogramData2}...}}
* *
* @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN. * @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 keyed histograms after snapshotting
* @param aClear Whether to clear out the subsession keyed histograms after snapshotting (only works if aSubsession is true)
*/ */
[implicit_jscontext] [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. * Create and return a histogram registered in TelemetryHistograms.h.