Bug 1470901 - Record scene build, scene swap, and render times in telemetry. r?sotaro draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 04 Jul 2018 07:52:22 -0400
changeset 814075 93e666c132f30ee6e2899ec162c225e8b2ea96d1
parent 814074 053705bc7d4230c1e528d0985ab2a2fa5c15d77d
push id115082
push userkgupta@mozilla.com
push dateWed, 04 Jul 2018 11:52:46 +0000
reviewerssotaro
bugs1470901
milestone63.0a1
Bug 1470901 - Record scene build, scene swap, and render times in telemetry. r?sotaro MozReview-Commit-ID: 1a6pqa0sSrU
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -24,16 +24,17 @@
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/SharedSurfacesParent.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/AsyncImagePipelineManager.h"
 #include "mozilla/layers/WebRenderImageHost.h"
 #include "mozilla/layers/WebRenderTextureHost.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/widget/CompositorWidget.h"
 
 bool is_in_main_thread()
 {
   return NS_IsMainThread();
@@ -119,16 +120,36 @@ gecko_profiler_register_thread(const cha
 }
 
 void
 gecko_profiler_unregister_thread()
 {
   PROFILER_UNREGISTER_THREAD();
 }
 
+void
+record_telemetry_time(mozilla::wr::TelemetryProbe aProbe, uint64_t aTimeNs)
+{
+  uint32_t time_ms = (uint32_t)(aTimeNs / 1000000);
+  switch (aProbe) {
+    case mozilla::wr::TelemetryProbe::SceneBuildTime:
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::WR_SCENEBUILD_TIME, time_ms);
+      break;
+    case mozilla::wr::TelemetryProbe::SceneSwapTime:
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::WR_SCENESWAP_TIME, time_ms);
+      break;
+    case mozilla::wr::TelemetryProbe::RenderTime:
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::WR_RENDER_TIME, time_ms);
+      break;
+    default:
+      MOZ_ASSERT(false);
+      break;
+  }
+}
+
 namespace mozilla {
 
 namespace layers {
 
 using namespace mozilla::gfx;
 
 class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender
 {
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -457,16 +457,23 @@ fn get_proc_address(glcontext_ptr: *mut 
     if symbol.is_null() {
         // XXX Bug 1322949 Make whitelist for extensions
         warn!("Could not find symbol {:?} by glcontext", symbol_name);
     }
 
     symbol as *const _
 }
 
+#[repr(C)]
+pub enum TelemetryProbe {
+    SceneBuildTime = 0,
+    SceneSwapTime = 1,
+    RenderTime = 2,
+}
+
 extern "C" {
     fn is_in_compositor_thread() -> bool;
     fn is_in_render_thread() -> bool;
     fn is_in_main_thread() -> bool;
     fn is_glcontext_egl(glcontext_ptr: *mut c_void) -> bool;
     fn is_glcontext_angle(glcontext_ptr: *mut c_void) -> bool;
     // Enables binary recording that can be used with `wrench replay`
     // Outputs a wr-record-*.bin file for each window that is shown
@@ -476,16 +483,17 @@ extern "C" {
     fn gfx_use_wrench() -> bool;
     fn gfx_wr_resource_path_override() -> *const c_char;
     // TODO: make gfx_critical_error() work.
     // We still have problem to pass the error message from render/render_backend
     // thread to main thread now.
     #[allow(dead_code)]
     fn gfx_critical_error(msg: *const c_char);
     fn gfx_critical_note(msg: *const c_char);
+    fn record_telemetry_time(probe: TelemetryProbe, time_ns: u64);
 }
 
 struct CppNotifier {
     window_id: WrWindowId,
 }
 
 unsafe impl Send for CppNotifier {}
 
@@ -510,18 +518,21 @@ impl RenderNotifier for CppNotifier {
             wr_notifier_wake_up(self.window_id);
         }
     }
 
     fn new_frame_ready(&self,
                        _: DocumentId,
                        _scrolled: bool,
                        composite_needed: bool,
-                       _render_time_ns: Option<u64>) {
+                       render_time_ns: Option<u64>) {
         unsafe {
+            if let Some(time) = render_time_ns {
+                record_telemetry_time(TelemetryProbe::RenderTime, time);
+            }
             if composite_needed {
                 wr_notifier_new_frame_ready(self.window_id);
             } else {
                 wr_notifier_nop_frame_done(self.window_id);
             }
         }
     }
 
@@ -713,23 +724,29 @@ impl APZCallbacks {
     }
 }
 
 impl SceneBuilderHooks for APZCallbacks {
     fn register(&self) {
         unsafe { apz_register_updater(self.window_id) }
     }
 
-    fn pre_scene_swap(&self, _scenebuild_time: u64) {
-        unsafe { apz_pre_scene_swap(self.window_id) }
+    fn pre_scene_swap(&self, scenebuild_time: u64) {
+        unsafe {
+            record_telemetry_time(TelemetryProbe::SceneBuildTime, scenebuild_time);
+            apz_pre_scene_swap(self.window_id);
+        }
     }
 
-    fn post_scene_swap(&self, info: PipelineInfo, _sceneswap_time: u64) {
+    fn post_scene_swap(&self, info: PipelineInfo, sceneswap_time: u64) {
         let info = WrPipelineInfo::new(info);
-        unsafe { apz_post_scene_swap(self.window_id, info) }
+        unsafe {
+            record_telemetry_time(TelemetryProbe::SceneSwapTime, sceneswap_time);
+            apz_post_scene_swap(self.window_id, info);
+        }
 
         // After a scene swap we should schedule a render for the next vsync,
         // otherwise there's no guarantee that the new scene will get rendered
         // anytime soon
         unsafe { wr_schedule_render(self.window_id) }
     }
 
     fn post_resource_update(&self) {
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -122,9 +122,15 @@ void apz_deregister_sampler(mozilla::wr:
 #  define WR_DESTRUCTOR_SAFE_FUNC {}
 #endif
 
 #include "webrender_ffi_generated.h"
 
 #undef WR_FUNC
 #undef WR_DESTRUCTOR_SAFE_FUNC
 
+// More functions invoked from Rust code. These are down here because they
+// refer to data structures from webrender_ffi_generated.h
+extern "C" {
+void record_telemetry_time(mozilla::wr::TelemetryProbe aProbe, uint64_t aTimeNs);
+}
+
 #endif // WR_h
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -147,16 +147,24 @@ enum class RepeatMode : uint32_t {
   Stretch,
   Repeat,
   Round,
   Space,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
+enum class TelemetryProbe {
+  SceneBuildTime = 0,
+  SceneSwapTime = 1,
+  RenderTime = 2,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
 enum class TransformStyle : uint32_t {
   Flat = 0,
   Preserve3D = 1,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 enum class WrAnimationType : uint32_t {
@@ -1000,16 +1008,19 @@ extern bool is_glcontext_angle(void *aGl
 extern bool is_glcontext_egl(void *aGlcontextPtr);
 
 extern bool is_in_compositor_thread();
 
 extern bool is_in_main_thread();
 
 extern bool is_in_render_thread();
 
+extern void record_telemetry_time(TelemetryProbe aProbe,
+                                  uint64_t aTimeNs);
+
 WR_INLINE
 bool remove_program_binary_disk_cache(const nsAString *aProfPath)
 WR_FUNC;
 
 WR_INLINE
 const VecU8 *wr_add_ref_arc(const ArcVecU8 *aArc)
 WR_FUNC;