Bug 1393399 P4 - implement GPUProcessCrashTelemetryLogger helper class; draft
authorKaku Kuo <kaku@mozilla.com>
Thu, 31 Aug 2017 17:56:17 +0800
changeset 657861 1a47f98d9f88f399cb1624655dabc6d01a11cfbc
parent 657860 49f4c2f7de4bd619ce03ff3e64be8892c5f37b50
child 657862 b01e1d9be5b7f80ea285359bdc13937ec5756e03
push id77648
push userbmo:kaku@mozilla.com
push dateSat, 02 Sep 2017 06:37:18 +0000
bugs1393399
milestone57.0a1
Bug 1393399 P4 - implement GPUProcessCrashTelemetryLogger helper class; GPUProcessCrashTelemetryLogger is used to report telemetry of the time used to recover a decoder from GPU crash. It uses MediaDecoderOwnerID to identify which video we're dealing with. It uses MediaDataDecoderID to make sure that the old MediaDataDecoder has been deleted and we're already recovered. It reports two recovery times, one is calculated from GPU crashed (that is, the time when VideoDecoderChild::ActorDestory() is called) and the other is calculated from the MFR is notified with NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER error. MozReview-Commit-ID: 82BRc2Vs3cw
dom/media/MediaFormatReader.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -21,16 +21,17 @@
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "nsContentUtils.h"
 #include "nsPrintfCString.h"
 
 #include <algorithm>
+#include <map>
 #include <queue>
 
 using namespace mozilla::media;
 
 using mozilla::layers::Image;
 using mozilla::layers::LayerManager;
 using mozilla::layers::LayersBackend;
 
@@ -39,16 +40,97 @@ mozilla::LazyLogModule gMediaDemuxerLog(
 
 #define LOG(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Debug, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #define LOGV(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 #define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
 
 namespace mozilla {
 
+
+typedef void* MediaDataDecoderID;
+
+/**
+ * This helper class is used to report telemetry of the time used to recover a
+ * decoder from GPU crash.
+ * It uses MediaDecoderOwnerID to identify which video we're dealing with.
+ * It uses MediaDataDecoderID to make sure that the old MediaDataDecoder has
+ * been deleted and we're already recovered.
+ * It reports two recovery times, one is calculated from GPU crashed (that is,
+ * the time when VideoDecoderChild::ActorDestory() is called) and the other is
+ * calculated from the MFR is notified with NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER
+ * error.
+ */
+class GPUProcessCrashTelemetryLogger
+{
+  struct GPUCrashData
+  {
+    GPUCrashData(MediaDataDecoderID aMediaDataDecoderID,
+                 mozilla::TimeStamp aGPUCrashTime,
+                 mozilla::TimeStamp aErrorNotifiedTime)
+      : mMediaDataDecoderID(aMediaDataDecoderID)
+      , mGPUCrashTime(aGPUCrashTime)
+      , mErrorNotifiedTime(aErrorNotifiedTime)
+    {
+      MOZ_ASSERT(mMediaDataDecoderID);
+      MOZ_ASSERT(!mGPUCrashTime.IsNull());
+      MOZ_ASSERT(!mErrorNotifiedTime.IsNull());
+    }
+
+    MediaDataDecoderID mMediaDataDecoderID;
+    mozilla::TimeStamp mGPUCrashTime;
+    mozilla::TimeStamp mErrorNotifiedTime;
+  };
+
+public:
+  static void
+  RecordGPUCrashData(MediaDecoderOwnerID aMediaDecoderOwnerID,
+                     MediaDataDecoderID aMediaDataDecoderID,
+                     const TimeStamp& aGPUCrashTime,
+                     const TimeStamp& aErrorNotifiedTime)
+  {
+    MOZ_ASSERT(aMediaDecoderOwnerID);
+    MOZ_ASSERT(aMediaDataDecoderID);
+    MOZ_ASSERT(!aGPUCrashTime.IsNull());
+    MOZ_ASSERT(!aErrorNotifiedTime.IsNull());
+    auto it = sGPUCrashDataMap.find(aMediaDecoderOwnerID);
+    if (it == sGPUCrashDataMap.end()) {
+      sGPUCrashDataMap.insert(std::make_pair(aMediaDecoderOwnerID,
+                                             GPUCrashData(aMediaDataDecoderID,
+                                                          aGPUCrashTime,
+                                                          aErrorNotifiedTime)));
+    }
+  }
+
+  static void
+  ReportTelemetry(MediaDecoderOwnerID aMediaDecoderOwnerID,
+                  MediaDataDecoderID aMediaDataDecoderID)
+  {
+    MOZ_ASSERT(aMediaDecoderOwnerID);
+    MOZ_ASSERT(aMediaDataDecoderID);
+    auto it = sGPUCrashDataMap.find(aMediaDecoderOwnerID);
+    if (it != sGPUCrashDataMap.end() &&
+        it->second.mMediaDataDecoderID != aMediaDataDecoderID) {
+      Telemetry::AccumulateTimeDelta(
+        Telemetry::VIDEO_HW_DECODER_CRASH_RECOVERY_TIME_SINCE_GPU_CRASHED_MS,
+        it->second.mGPUCrashTime);
+      Telemetry::AccumulateTimeDelta(
+        Telemetry::VIDEO_HW_DECODER_CRASH_RECOVERY_TIME_SINCE_MFR_NOTIFIED_MS,
+        it->second.mErrorNotifiedTime);
+      sGPUCrashDataMap.erase(aMediaDecoderOwnerID);
+    }
+  }
+
+private:
+  static std::map<MediaDecoderOwnerID, GPUCrashData> sGPUCrashDataMap;
+};
+
+std::map<MediaDecoderOwnerID, GPUProcessCrashTelemetryLogger::GPUCrashData>
+GPUProcessCrashTelemetryLogger::sGPUCrashDataMap;
+
 /**
  * This is a singleton which controls the number of decoders that can be
  * created concurrently. Before calling PDMFactory::CreateDecoder(), Alloc()
  * must be called to get a token object as a permission to create a decoder.
  * The token should stay alive until Shutdown() is called on the decoder.
  * The destructor of the token will restore the decoder count so it is available
  * for next calls of Alloc().
  */