Bug 1436680 - Allow non-templated uses of AutoTimer. r?chutten,janv draft
authorJeremy Lempereur <jeremy.lempereur@gmail.com>
Tue, 13 Feb 2018 15:23:09 +0100
changeset 765950 d6e2730c400b211a5df5c0eb6a7d49a2bf02170c
parent 754399 38b3c1d03a594664c6b32c35533734283c258f43
child 765951 0f302a3664d76028074854a3b7ec219acbd344f2
child 765952 347ad94c176e95a28a581c879ca66f90f5bc6477
push id102189
push userbmo:jeremy.lempereur@gmail.com
push dateSun, 11 Mar 2018 13:23:33 +0000
reviewerschutten, janv
bugs1436680
milestone60.0a1
Bug 1436680 - Allow non-templated uses of AutoTimer. r?chutten,janv Moved the runtime Telemetry::AutoTimer implementation to the Telemetry public API. MozReview-Commit-ID: KNT6toDQUtR
dom/storage/LocalStorageCache.cpp
toolkit/components/telemetry/Telemetry.h
toolkit/components/telemetry/docs/collection/histograms.rst
toolkit/components/telemetry/docs/collection/measuring-time.rst
--- a/dom/storage/LocalStorageCache.cpp
+++ b/dom/storage/LocalStorageCache.cpp
@@ -244,40 +244,16 @@ LocalStorageCache::Preload()
     mLoaded = true;
     mLoadResult = NS_ERROR_FAILURE;
     return;
   }
 
   storageChild->AsyncPreload(this);
 }
 
-namespace {
-
-// The AutoTimer provided by telemetry headers is only using static,
-// i.e. compile time known ID, but here we know the ID only at run time.
-// Hence a new class.
-class TelemetryAutoTimer
-{
-public:
-  explicit TelemetryAutoTimer(Telemetry::HistogramID aId)
-    : id(aId), start(TimeStamp::Now())
-  {}
-
-  ~TelemetryAutoTimer()
-  {
-    Telemetry::AccumulateTimeDelta(id, start);
-  }
-
-private:
-  Telemetry::HistogramID id;
-  const TimeStamp start;
-};
-
-} // namespace
-
 void
 LocalStorageCache::WaitForPreload(Telemetry::HistogramID aTelemetryID)
 {
   if (!mPersistent) {
     return;
   }
 
   bool loaded = mLoaded;
@@ -290,17 +266,17 @@ LocalStorageCache::WaitForPreload(Teleme
       !loaded);
   }
 
   if (loaded) {
     return;
   }
 
   // Measure which operation blocks and for how long
-  TelemetryAutoTimer timer(aTelemetryID);
+  Telemetry::RuntimeAutoTimer timer(aTelemetryID);
 
   // If preload already started (i.e. we got some first data, but not all)
   // SyncPreload will just wait for it to finish rather then synchronously
   // read from the database.  It seems to me more optimal.
 
   // TODO place for A/B testing (force main thread load vs. let preload finish)
 
   // No need to check sDatabase for being non-null since preload is either
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -229,16 +229,55 @@ AccumulateTimeDelta(HistogramID id,
  *
  * @param id - histogram id
  * @param enabled - whether or not to enable recording from now on.
  */
 void SetHistogramRecordingEnabled(HistogramID id, bool enabled);
 
 const char* GetHistogramName(HistogramID id);
 
+class MOZ_RAII RuntimeAutoTimer
+{
+public:
+  explicit RuntimeAutoTimer(Telemetry::HistogramID aId,
+                            TimeStamp aStart = TimeStamp::Now()
+                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+    : id(aId)
+    , start(aStart)
+  {
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+  }
+  explicit RuntimeAutoTimer(Telemetry::HistogramID aId,
+                            const nsCString& aKey,
+                            TimeStamp aStart = TimeStamp::Now()
+                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+    : id(aId)
+    , key(aKey)
+    , start(aStart)
+  {
+    MOZ_ASSERT(!aKey.IsEmpty(), "The key must not be empty.");
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+  }
+
+  ~RuntimeAutoTimer()
+  {
+    if (key.IsEmpty()) {
+      AccumulateTimeDelta(id, start);
+    } else {
+      AccumulateTimeDelta(id, key, start);
+    }
+  }
+
+private:
+  Telemetry::HistogramID id;
+  const nsCString key;
+  const TimeStamp start;
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 template<HistogramID id>
 class MOZ_RAII AutoTimer
 {
 public:
   explicit AutoTimer(TimeStamp aStart = TimeStamp::Now() MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
      : start(aStart)
   {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
--- a/toolkit/components/telemetry/docs/collection/histograms.rst
+++ b/toolkit/components/telemetry/docs/collection/histograms.rst
@@ -316,8 +316,22 @@ The ``Telemetry.h`` header also declares
 
   nsresult
   nsPluginHost::StopPluginInstance(nsNPAPIPluginInstance* aInstance)
   {
     Telemetry::AutoTimer<Telemetry::PLUGIN_SHUTDOWN_MS> timer;
     ...
     return NS_OK;
   }
+
+If the HistogramID is not known at compile time, one can use the ``RuntimeAutoTimer`` class, which behaves like the template parameterized ``AutoTimer``.
+
+.. code-block:: cpp
+
+  void
+  FunctionWithTiming(Telemetry::HistogramID aTelemetryID)
+  {
+    ...
+    Telemetry::RuntimeAutoTimer timer(aTelemetryID);
+    ...
+  }
+
+Prefer using the template parameterized ``AutoTimer`` and ``AutoCounter`` on hot paths, if possible.
--- a/toolkit/components/telemetry/docs/collection/measuring-time.rst
+++ b/toolkit/components/telemetry/docs/collection/measuring-time.rst
@@ -79,20 +79,38 @@ API:
     class AutoTimer {
       // Record into a plain histogram.
       explicit AutoTimer(TimeStamp aStart = TimeStamp::Now());
       // Record into a keyed histogram, with key |aKey|.
       explicit AutoTimer(const nsCString& aKey,
                          TimeStamp aStart = TimeStamp::Now());
     };
 
+    // If the Histogram id is not known at compile time:
+    class RuntimeAutoTimer {
+      // Record into a plain histogram.
+      explicit RuntimeAutoTimer(Telemetry::HistogramID aId,
+                            TimeStamp aStart = TimeStamp::Now());
+      // Record into a keyed histogram, with key |aKey|.
+      explicit RuntimeAutoTimer(Telemetry::HistogramID aId,
+                            const nsCString& aKey,
+                            TimeStamp aStart = TimeStamp::Now());
+    };
+
     void AccumulateTimeDelta(HistogramID id, TimeStamp start, TimeStamp end = TimeStamp::Now());
     void AccumulateTimeDelta(HistogramID id, const nsCString& key, TimeStamp start, TimeStamp end = TimeStamp::Now());
 
 Example:
 
 .. code-block:: cpp
 
     {
       Telemetry::AutoTimer<Telemetry::FIND_PLUGINS> telemetry;
       // ... scan disk for plugins.
     }
     // When leaving the scope, AutoTimers destructor will record the time that passed.
+
+    // If the histogram id is not known at compile time.
+    {
+      Telemetry::RuntimeAutoTimer telemetry(Telemetry::FIND_PLUGINS);
+      // ... scan disk for plugins.
+    }
+    // When leaving the scope, AutoTimers destructor will record the time that passed.