Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(983)

Unified Diff: content/browser/renderer_host/render_widget_host_latency_tracker.cc

Issue 779763002: Factor out latency tracking from RenderWidgetHostImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Restore original owners Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/renderer_host/render_widget_host_latency_tracker.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/renderer_host/render_widget_host_latency_tracker.cc
diff --git a/content/browser/renderer_host/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/render_widget_host_latency_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fc62885b39dbf9dfd55ba5eb30d36d3145538ea1
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_host_latency_tracker.cc
@@ -0,0 +1,308 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_latency_tracker.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using ui::LatencyInfo;
+
+namespace content {
+namespace {
+
+const uint32 kMaxInputCoordinates = LatencyInfo::kMaxInputCoordinates;
+
+void UpdateLatencyCoordinatesImpl(const blink::WebTouchEvent& touch,
+ LatencyInfo* latency) {
+ latency->input_coordinates_size =
+ std::min(kMaxInputCoordinates, touch.touchesLength);
+ for (uint32 i = 0; i < latency->input_coordinates_size; ++i) {
+ latency->input_coordinates[i] = LatencyInfo::InputCoordinate(
+ touch.touches[i].position.x, touch.touches[i].position.y);
+ }
+}
+
+void UpdateLatencyCoordinatesImpl(const WebGestureEvent& gesture,
+ LatencyInfo* latency) {
+ latency->input_coordinates_size = 1;
+ latency->input_coordinates[0] =
+ LatencyInfo::InputCoordinate(gesture.x, gesture.y);
+}
+
+void UpdateLatencyCoordinatesImpl(const WebMouseEvent& mouse,
+ LatencyInfo* latency) {
+ latency->input_coordinates_size = 1;
+ latency->input_coordinates[0] =
+ LatencyInfo::InputCoordinate(mouse.x, mouse.y);
+}
+
+void UpdateLatencyCoordinatesImpl(const WebMouseWheelEvent& wheel,
+ LatencyInfo* latency) {
+ latency->input_coordinates_size = 1;
+ latency->input_coordinates[0] =
+ LatencyInfo::InputCoordinate(wheel.x, wheel.y);
+}
+
+void UpdateLatencyCoordinates(const WebInputEvent& event,
+ float device_scale_factor,
+ LatencyInfo* latency) {
+ if (WebInputEvent::isMouseEventType(event.type)) {
+ UpdateLatencyCoordinatesImpl(static_cast<const WebMouseEvent&>(event),
+ latency);
+ } else if (WebInputEvent::isGestureEventType(event.type)) {
+ UpdateLatencyCoordinatesImpl(static_cast<const WebGestureEvent&>(event),
+ latency);
+ } else if (WebInputEvent::isTouchEventType(event.type)) {
+ UpdateLatencyCoordinatesImpl(static_cast<const WebTouchEvent&>(event),
+ latency);
+ } else if (event.type == WebInputEvent::MouseWheel) {
+ UpdateLatencyCoordinatesImpl(static_cast<const WebMouseWheelEvent&>(event),
+ latency);
+ }
+ if (device_scale_factor == 1)
+ return;
+ for (uint32 i = 0; i < latency->input_coordinates_size; ++i) {
+ latency->input_coordinates[i].x *= device_scale_factor;
+ latency->input_coordinates[i].y *= device_scale_factor;
+ }
+}
+
+void ComputeInputLatencyHistograms(WebInputEvent::Type type,
+ int64 latency_component_id,
+ const LatencyInfo& latency) {
+ LatencyInfo::LatencyComponent rwh_component;
+ if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ latency_component_id, &rwh_component)) {
+ return;
+ }
+ DCHECK_EQ(rwh_component.event_count, 1u);
+
+ LatencyInfo::LatencyComponent ui_component;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0,
+ &ui_component)) {
+ DCHECK_EQ(ui_component.event_count, 1u);
+ base::TimeDelta ui_delta =
+ rwh_component.event_time - ui_component.event_time;
+ switch (type) {
+ case blink::WebInputEvent::MouseWheel:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.WheelUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+ break;
+ case blink::WebInputEvent::TouchTypeFirst:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.TouchUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ LatencyInfo::LatencyComponent acked_component;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ &acked_component)) {
+ DCHECK_EQ(acked_component.event_count, 1u);
+ base::TimeDelta acked_delta =
+ acked_component.event_time - rwh_component.event_time;
+ switch (type) {
+ case blink::WebInputEvent::MouseWheel:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.WheelAcked",
+ acked_delta.InMicroseconds(), 1, 1000000, 100);
+ break;
+ case blink::WebInputEvent::TouchTypeFirst:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.TouchAcked",
+ acked_delta.InMicroseconds(), 1, 1000000, 100);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+// LatencyComponents generated in the renderer must have component IDs
+// provided to them by the browser process. This function adds the correct
+// component ID where necessary.
+void AddLatencyInfoComponentIds(LatencyInfo* latency,
+ int64 latency_component_id) {
+ LatencyInfo::LatencyMap new_components;
+ auto lc = latency->latency_components.begin();
+ while (lc != latency->latency_components.end()) {
+ ui::LatencyComponentType component_type = lc->first.first;
+ if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
+ component_type == ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
+ // Generate a new component entry with the correct component ID
+ auto key = std::make_pair(component_type, latency_component_id);
+ new_components[key] = lc->second;
+
+ // Remove the old entry
+ latency->latency_components.erase(lc++);
+ } else {
+ ++lc;
+ }
+ }
+
+ // Add newly generated components into the latency info
+ for (lc = new_components.begin(); lc != new_components.end(); ++lc) {
+ latency->latency_components[lc->first] = lc->second;
+ }
+}
+
+} // namespace
+
+RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker()
+ : last_event_id_(0), latency_component_id_(0), device_scale_factor_(1) {
+}
+
+RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {
+}
+
+void RenderWidgetHostLatencyTracker::Initialize(int routing_id,
+ int process_id) {
+ DCHECK_EQ(0, last_event_id_);
+ DCHECK_EQ(0, latency_component_id_);
+ last_event_id_ = static_cast<int64>(process_id) << 32;
+ latency_component_id_ = routing_id | last_event_id_;
+}
+
+void RenderWidgetHostLatencyTracker::OnInputEvent(
+ const blink::WebInputEvent& event,
+ LatencyInfo* latency) {
+ DCHECK(latency);
+ if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ latency_component_id_, NULL)) {
+ return;
+ }
+
+ latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ latency_component_id_, ++last_event_id_);
+ latency->TraceEventType(WebInputEventTraits::GetName(event.type));
+ UpdateLatencyCoordinates(event, device_scale_factor_, latency);
+
+ if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
+ latency->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
+ latency_component_id_, ++last_event_id_);
+
+ // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
+ // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
+ // So we can track the latency specifically for scroll update events.
+ LatencyInfo::LatencyComponent original_component;
+ if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ &original_component)) {
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ latency_component_id_, original_component.sequence_number,
+ original_component.event_time, original_component.event_count);
+ }
+ }
+}
+
+void RenderWidgetHostLatencyTracker::OnInputEventAck(
+ const blink::WebInputEvent& event,
+ LatencyInfo* latency) {
+ DCHECK(latency);
+
+ // Latency ends when it is acked but does not cause render scheduling.
+ bool rendering_scheduled = latency->FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL);
+
+ if (WebInputEvent::isGestureEventType(event.type)) {
+ if (rendering_scheduled) {
+ latency->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0);
+ // TODO(jdduke): Consider exposing histograms for gesture event types.
+ }
+ return;
+ }
+
+ if (WebInputEvent::isTouchEventType(event.type)) {
+ latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
+ if (rendering_scheduled) {
+ latency->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0);
+ ComputeInputLatencyHistograms(WebInputEvent::TouchTypeFirst,
+ latency_component_id_, *latency);
+ }
+ return;
+ }
+
+ if (event.type == WebInputEvent::MouseWheel) {
+ latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
+ if (rendering_scheduled) {
+ latency->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
+ ComputeInputLatencyHistograms(WebInputEvent::MouseWheel,
+ latency_component_id_, *latency);
+ }
+ return;
+ }
+
+ // TODO(jdduke): Determine if mouse and keyboard events are worth hooking
+ // into LatencyInfo.
+}
+
+void RenderWidgetHostLatencyTracker::OnSwapCompositorFrame(
+ std::vector<LatencyInfo>* latencies) {
+ DCHECK(latencies);
+ for (LatencyInfo& latency : *latencies)
+ AddLatencyInfoComponentIds(&latency, latency_component_id_);
+}
+
+void RenderWidgetHostLatencyTracker::OnFrameSwapped(
+ const ui::LatencyInfo& latency) {
+ LatencyInfo::LatencyComponent swap_component;
+ if (!latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
+ &swap_component)) {
+ return;
+ }
+
+ LatencyInfo::LatencyComponent tab_switch_component;
+ if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, latency_component_id_,
+ &tab_switch_component)) {
+ base::TimeDelta delta =
+ swap_component.event_time - tab_switch_component.event_time;
+ for (size_t i = 0; i < tab_switch_component.event_count; i++) {
+ UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta);
+ }
+ }
+
+ LatencyInfo::LatencyComponent rwh_component;
+ if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ latency_component_id_, &rwh_component)) {
+ return;
+ }
+
+ LatencyInfo::LatencyComponent original_component;
+ if (latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ latency_component_id_, &original_component)) {
+ // This UMA metric tracks the time from when the original touch event is
+ // created (averaged if there are multiple) to when the scroll gesture
+ // results in final frame swap.
+ for (size_t i = 0; i < original_component.event_count; i++) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.TouchToScrollUpdateSwap",
+ (swap_component.event_time - original_component.event_time)
+ .InMicroseconds(),
+ 1,
+ 1000000,
+ 100);
+ }
+ }
+}
+
+} // namespace content
« no previous file with comments | « content/browser/renderer_host/render_widget_host_latency_tracker.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698