зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1768636 - Scope GIFFT timer maps to metrics r=TravisLong
TimerIds are only unique for a given metric, not globally. Differential Revision: https://phabricator.services.mozilla.com/D145988
This commit is contained in:
Родитель
a3bbcd490c
Коммит
14fee064de
|
@ -9,6 +9,7 @@
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "mozilla/Components.h"
|
#include "mozilla/Components.h"
|
||||||
#include "mozilla/ResultVariant.h"
|
#include "mozilla/ResultVariant.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/dom/ToJSValue.h"
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
#include "mozilla/glean/bindings/HistogramGIFFTMap.h"
|
#include "mozilla/glean/bindings/HistogramGIFFTMap.h"
|
||||||
#include "mozilla/glean/fog_ffi_generated.h"
|
#include "mozilla/glean/fog_ffi_generated.h"
|
||||||
|
@ -24,8 +25,11 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStart(
|
||||||
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
||||||
if (mirrorId) {
|
if (mirrorId) {
|
||||||
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
|
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
|
||||||
(void)NS_WARN_IF(lock.ref()->Remove(aTimerId));
|
auto tuple = mozilla::MakeTuple(aMetricId, aTimerId);
|
||||||
lock.ref()->InsertOrUpdate(aTimerId, mozilla::TimeStamp::Now());
|
// It should be all but impossible for anyone to have already inserted
|
||||||
|
// this timer for this metric given the monotonicity of timer ids.
|
||||||
|
(void)NS_WARN_IF(lock.ref()->Remove(tuple));
|
||||||
|
lock.ref()->InsertOrUpdate(tuple, mozilla::TimeStamp::Now());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +40,10 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionStopAndAccumulate(
|
||||||
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
||||||
if (mirrorId) {
|
if (mirrorId) {
|
||||||
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
|
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
|
||||||
auto optStart = lock.ref()->Extract(aTimerId);
|
auto optStart =
|
||||||
|
lock.ref()->Extract(mozilla::MakeTuple(aMetricId, aTimerId));
|
||||||
|
// The timer might not be in the map to be removed if it's already been
|
||||||
|
// cancelled or stop_and_accumulate'd.
|
||||||
if (!NS_WARN_IF(!optStart)) {
|
if (!NS_WARN_IF(!optStart)) {
|
||||||
AccumulateTimeDelta(mirrorId.extract(), optStart.extract());
|
AccumulateTimeDelta(mirrorId.extract(), optStart.extract());
|
||||||
}
|
}
|
||||||
|
@ -58,8 +65,12 @@ extern "C" NS_EXPORT void GIFFT_TimingDistributionCancel(
|
||||||
uint32_t aMetricId, mozilla::glean::TimerId aTimerId) {
|
uint32_t aMetricId, mozilla::glean::TimerId aTimerId) {
|
||||||
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
auto mirrorId = mozilla::glean::HistogramIdForMetric(aMetricId);
|
||||||
if (mirrorId) {
|
if (mirrorId) {
|
||||||
mozilla::glean::GetTimerIdToStartsLock().apply(
|
mozilla::glean::GetTimerIdToStartsLock().apply([&](auto& lock) {
|
||||||
[&](auto& lock) { (void)NS_WARN_IF(!lock.ref()->Remove(aTimerId)); });
|
// The timer might not be in the map to be removed if it's already been
|
||||||
|
// cancelled or stop_and_accumulate'd.
|
||||||
|
(void)NS_WARN_IF(
|
||||||
|
!lock.ref()->Remove(mozilla::MakeTuple(aMetricId, aTimerId)));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
It is only for internal use by types in
|
It is only for internal use by types in
|
||||||
toolkit/components/glean/bindings/private */
|
toolkit/components/glean/bindings/private */
|
||||||
{# The rendered source is autogenerated, but this
|
{# The rendered source is autogenerated, but this
|
||||||
Jinja2 template is not. Pleas file bugs! #}
|
Jinja2 template is not. Please file bugs! #}
|
||||||
|
|
||||||
#include "mozilla/AppShutdown.h"
|
#include "mozilla/AppShutdown.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/DataMutex.h"
|
#include "mozilla/DataMutex.h"
|
||||||
{% if probe_type == "Scalar" %}
|
{% if probe_type == "Scalar" %}
|
||||||
#include "mozilla/Tuple.h"
|
#include "mozilla/Tuple.h"
|
||||||
|
@ -27,8 +28,38 @@ namespace mozilla::glean {
|
||||||
using Telemetry::{{ probe_type }}ID;
|
using Telemetry::{{ probe_type }}ID;
|
||||||
|
|
||||||
{% if probe_type == "Histogram" %}
|
{% if probe_type == "Histogram" %}
|
||||||
typedef uint64_t TimerId; // Same as in TimingDistribution.h.
|
|
||||||
typedef StaticDataMutex<UniquePtr<nsTHashMap<TimerId, TimeStamp>>> TimerToStampMutex;
|
using MetricId = uint32_t; // Same type as in api/src/private/mod.rs
|
||||||
|
using TimerId = uint64_t; // Same as in TimingDistribution.h.
|
||||||
|
using MetricTimerTuple = Tuple<MetricId, TimerId>;
|
||||||
|
class MetricTimerTupleHashKey : public PLDHashEntryHdr {
|
||||||
|
public:
|
||||||
|
using KeyType = const MetricTimerTuple&;
|
||||||
|
using KeyTypePointer = const MetricTimerTuple*;
|
||||||
|
|
||||||
|
explicit MetricTimerTupleHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
|
||||||
|
MetricTimerTupleHashKey(MetricTimerTupleHashKey&& aOther)
|
||||||
|
: PLDHashEntryHdr(std::move(aOther)),
|
||||||
|
mValue(std::move(aOther.mValue)) {}
|
||||||
|
~MetricTimerTupleHashKey() = default;
|
||||||
|
|
||||||
|
KeyType GetKey() const { return mValue; }
|
||||||
|
bool KeyEquals(KeyTypePointer aKey) const {
|
||||||
|
return Get<0>(*aKey) == Get<0>(mValue) && Get<1>(*aKey) == Get<1>(mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||||
|
static PLDHashNumber HashKey(KeyTypePointer aKey) {
|
||||||
|
// Chosen because this is how nsIntegralHashKey does it.
|
||||||
|
return HashGeneric(Get<0>(*aKey), Get<1>(*aKey));
|
||||||
|
}
|
||||||
|
enum { ALLOW_MEMMOVE = true };
|
||||||
|
|
||||||
|
private:
|
||||||
|
const MetricTimerTuple mValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StaticDataMutex<UniquePtr<nsTHashMap<MetricTimerTupleHashKey, TimeStamp>>> TimerToStampMutex;
|
||||||
static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
||||||
static TimerToStampMutex sTimerIdToStarts("sTimerIdToStarts");
|
static TimerToStampMutex sTimerIdToStarts("sTimerIdToStarts");
|
||||||
auto lock = sTimerIdToStarts.Lock();
|
auto lock = sTimerIdToStarts.Lock();
|
||||||
|
@ -37,7 +68,7 @@ static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
if (!*lock) {
|
if (!*lock) {
|
||||||
*lock = MakeUnique<nsTHashMap<TimerId, TimeStamp>>();
|
*lock = MakeUnique<nsTHashMap<MetricTimerTupleHashKey, TimeStamp>>();
|
||||||
RefPtr<nsIRunnable> cleanupFn = NS_NewRunnableFunction(__func__, [&] {
|
RefPtr<nsIRunnable> cleanupFn = NS_NewRunnableFunction(__func__, [&] {
|
||||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
|
if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
|
||||||
auto lock = sTimerIdToStarts.Lock();
|
auto lock = sTimerIdToStarts.Lock();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/DataMutex.h"
|
#include "mozilla/DataMutex.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/DataMutex.h"
|
#include "mozilla/DataMutex.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
|
@ -18,8 +19,38 @@ namespace mozilla::glean {
|
||||||
|
|
||||||
using Telemetry::HistogramID;
|
using Telemetry::HistogramID;
|
||||||
|
|
||||||
typedef uint64_t TimerId; // Same as in TimingDistribution.h.
|
|
||||||
typedef StaticDataMutex<UniquePtr<nsTHashMap<TimerId, TimeStamp>>> TimerToStampMutex;
|
using MetricId = uint32_t; // Same type as in api/src/private/mod.rs
|
||||||
|
using TimerId = uint64_t; // Same as in TimingDistribution.h.
|
||||||
|
using MetricTimerTuple = Tuple<MetricId, TimerId>;
|
||||||
|
class MetricTimerTupleHashKey : public PLDHashEntryHdr {
|
||||||
|
public:
|
||||||
|
using KeyType = const MetricTimerTuple&;
|
||||||
|
using KeyTypePointer = const MetricTimerTuple*;
|
||||||
|
|
||||||
|
explicit MetricTimerTupleHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
|
||||||
|
MetricTimerTupleHashKey(MetricTimerTupleHashKey&& aOther)
|
||||||
|
: PLDHashEntryHdr(std::move(aOther)),
|
||||||
|
mValue(std::move(aOther.mValue)) {}
|
||||||
|
~MetricTimerTupleHashKey() = default;
|
||||||
|
|
||||||
|
KeyType GetKey() const { return mValue; }
|
||||||
|
bool KeyEquals(KeyTypePointer aKey) const {
|
||||||
|
return Get<0>(*aKey) == Get<0>(mValue) && Get<1>(*aKey) == Get<1>(mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||||
|
static PLDHashNumber HashKey(KeyTypePointer aKey) {
|
||||||
|
// Chosen because this is how nsIntegralHashKey does it.
|
||||||
|
return HashGeneric(Get<0>(*aKey), Get<1>(*aKey));
|
||||||
|
}
|
||||||
|
enum { ALLOW_MEMMOVE = true };
|
||||||
|
|
||||||
|
private:
|
||||||
|
const MetricTimerTuple mValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StaticDataMutex<UniquePtr<nsTHashMap<MetricTimerTupleHashKey, TimeStamp>>> TimerToStampMutex;
|
||||||
static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
||||||
static TimerToStampMutex sTimerIdToStarts("sTimerIdToStarts");
|
static TimerToStampMutex sTimerIdToStarts("sTimerIdToStarts");
|
||||||
auto lock = sTimerIdToStarts.Lock();
|
auto lock = sTimerIdToStarts.Lock();
|
||||||
|
@ -28,7 +59,7 @@ static inline Maybe<TimerToStampMutex::AutoLock> GetTimerIdToStartsLock() {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
if (!*lock) {
|
if (!*lock) {
|
||||||
*lock = MakeUnique<nsTHashMap<TimerId, TimeStamp>>();
|
*lock = MakeUnique<nsTHashMap<MetricTimerTupleHashKey, TimeStamp>>();
|
||||||
RefPtr<nsIRunnable> cleanupFn = NS_NewRunnableFunction(__func__, [&] {
|
RefPtr<nsIRunnable> cleanupFn = NS_NewRunnableFunction(__func__, [&] {
|
||||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
|
if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
|
||||||
auto lock = sTimerIdToStarts.Lock();
|
auto lock = sTimerIdToStarts.Lock();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/DataMutex.h"
|
#include "mozilla/DataMutex.h"
|
||||||
#include "mozilla/Tuple.h"
|
#include "mozilla/Tuple.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
|
|
|
@ -160,6 +160,7 @@ test_only:
|
||||||
- glean-team@mozilla.com
|
- glean-team@mozilla.com
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- test-ping
|
- test-ping
|
||||||
|
telemetry_mirror: TELEMETRY_TEST_MIRROR_FOR_TIMING
|
||||||
|
|
||||||
mabels_kitchen_counters:
|
mabels_kitchen_counters:
|
||||||
type: labeled_counter
|
type: labeled_counter
|
||||||
|
|
|
@ -119,7 +119,12 @@ add_task(function test_gifft_custom_dist() {
|
||||||
|
|
||||||
add_task(async function test_gifft_timing_dist() {
|
add_task(async function test_gifft_timing_dist() {
|
||||||
let t1 = Glean.testOnlyIpc.aTimingDist.start();
|
let t1 = Glean.testOnlyIpc.aTimingDist.start();
|
||||||
|
// Interleave some other metric's samples. bug 1768636.
|
||||||
|
let ot1 = Glean.testOnly.whatTimeIsIt.start();
|
||||||
let t2 = Glean.testOnlyIpc.aTimingDist.start();
|
let t2 = Glean.testOnlyIpc.aTimingDist.start();
|
||||||
|
let ot2 = Glean.testOnly.whatTimeIsIt.start();
|
||||||
|
Glean.testOnly.whatTimeIsIt.cancel(ot1);
|
||||||
|
Glean.testOnly.whatTimeIsIt.cancel(ot2);
|
||||||
|
|
||||||
await sleep(5);
|
await sleep(5);
|
||||||
|
|
||||||
|
|
|
@ -9755,6 +9755,19 @@
|
||||||
"releaseChannelCollection": "opt-out",
|
"releaseChannelCollection": "opt-out",
|
||||||
"description": "a testing histogram; not meant to be touched"
|
"description": "a testing histogram; not meant to be touched"
|
||||||
},
|
},
|
||||||
|
"TELEMETRY_TEST_MIRROR_FOR_TIMING": {
|
||||||
|
"record_in_processes": ["main", "content"],
|
||||||
|
"products": ["firefox"],
|
||||||
|
"alert_emails": ["chutten@mozilla.com"],
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "linear",
|
||||||
|
"low": 1,
|
||||||
|
"high": 2147483646,
|
||||||
|
"n_buckets": 10,
|
||||||
|
"bug_numbers": [1768636],
|
||||||
|
"releaseChannelCollection": "opt-out",
|
||||||
|
"description": "a testing histogram; not meant to be touched"
|
||||||
|
},
|
||||||
"TELEMETRY_TEST_BOOLEAN": {
|
"TELEMETRY_TEST_BOOLEAN": {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"products": ["firefox", "fennec", "thunderbird"],
|
"products": ["firefox", "fennec", "thunderbird"],
|
||||||
|
|
Загрузка…
Ссылка в новой задаче