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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/render_widget_host_latency_tracker.h"
6
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "content/browser/renderer_host/render_widget_host_impl.h"
10
11 using blink::WebGestureEvent;
12 using blink::WebInputEvent;
13 using blink::WebMouseEvent;
14 using blink::WebMouseWheelEvent;
15 using blink::WebTouchEvent;
16 using ui::LatencyInfo;
17
18 namespace content {
19 namespace {
20
21 const uint32 kMaxInputCoordinates = LatencyInfo::kMaxInputCoordinates;
22
23 void UpdateLatencyCoordinatesImpl(const blink::WebTouchEvent& touch,
24 LatencyInfo* latency) {
25 latency->input_coordinates_size =
26 std::min(kMaxInputCoordinates, touch.touchesLength);
27 for (uint32 i = 0; i < latency->input_coordinates_size; ++i) {
28 latency->input_coordinates[i] = LatencyInfo::InputCoordinate(
29 touch.touches[i].position.x, touch.touches[i].position.y);
30 }
31 }
32
33 void UpdateLatencyCoordinatesImpl(const WebGestureEvent& gesture,
34 LatencyInfo* latency) {
35 latency->input_coordinates_size = 1;
36 latency->input_coordinates[0] =
37 LatencyInfo::InputCoordinate(gesture.x, gesture.y);
38 }
39
40 void UpdateLatencyCoordinatesImpl(const WebMouseEvent& mouse,
41 LatencyInfo* latency) {
42 latency->input_coordinates_size = 1;
43 latency->input_coordinates[0] =
44 LatencyInfo::InputCoordinate(mouse.x, mouse.y);
45 }
46
47 void UpdateLatencyCoordinatesImpl(const WebMouseWheelEvent& wheel,
48 LatencyInfo* latency) {
49 latency->input_coordinates_size = 1;
50 latency->input_coordinates[0] =
51 LatencyInfo::InputCoordinate(wheel.x, wheel.y);
52 }
53
54 void UpdateLatencyCoordinates(const WebInputEvent& event,
55 float device_scale_factor,
56 LatencyInfo* latency) {
57 if (WebInputEvent::isMouseEventType(event.type)) {
58 UpdateLatencyCoordinatesImpl(static_cast<const WebMouseEvent&>(event),
59 latency);
60 } else if (WebInputEvent::isGestureEventType(event.type)) {
61 UpdateLatencyCoordinatesImpl(static_cast<const WebGestureEvent&>(event),
62 latency);
63 } else if (WebInputEvent::isTouchEventType(event.type)) {
64 UpdateLatencyCoordinatesImpl(static_cast<const WebTouchEvent&>(event),
65 latency);
66 } else if (event.type == WebInputEvent::MouseWheel) {
67 UpdateLatencyCoordinatesImpl(static_cast<const WebMouseWheelEvent&>(event),
68 latency);
69 }
70 if (device_scale_factor == 1)
71 return;
72 for (uint32 i = 0; i < latency->input_coordinates_size; ++i) {
73 latency->input_coordinates[i].x *= device_scale_factor;
74 latency->input_coordinates[i].y *= device_scale_factor;
75 }
76 }
77
78 void ComputeInputLatencyHistograms(WebInputEvent::Type type,
79 int64 latency_component_id,
80 const LatencyInfo& latency) {
81 LatencyInfo::LatencyComponent rwh_component;
82 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
83 latency_component_id, &rwh_component)) {
84 return;
85 }
86 DCHECK_EQ(rwh_component.event_count, 1u);
87
88 LatencyInfo::LatencyComponent ui_component;
89 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0,
90 &ui_component)) {
91 DCHECK_EQ(ui_component.event_count, 1u);
92 base::TimeDelta ui_delta =
93 rwh_component.event_time - ui_component.event_time;
94 switch (type) {
95 case blink::WebInputEvent::MouseWheel:
96 UMA_HISTOGRAM_CUSTOM_COUNTS(
97 "Event.Latency.Browser.WheelUI",
98 ui_delta.InMicroseconds(), 1, 20000, 100);
99 break;
100 case blink::WebInputEvent::TouchTypeFirst:
101 UMA_HISTOGRAM_CUSTOM_COUNTS(
102 "Event.Latency.Browser.TouchUI",
103 ui_delta.InMicroseconds(), 1, 20000, 100);
104 break;
105 default:
106 NOTREACHED();
107 break;
108 }
109 }
110
111 LatencyInfo::LatencyComponent acked_component;
112 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
113 &acked_component)) {
114 DCHECK_EQ(acked_component.event_count, 1u);
115 base::TimeDelta acked_delta =
116 acked_component.event_time - rwh_component.event_time;
117 switch (type) {
118 case blink::WebInputEvent::MouseWheel:
119 UMA_HISTOGRAM_CUSTOM_COUNTS(
120 "Event.Latency.Browser.WheelAcked",
121 acked_delta.InMicroseconds(), 1, 1000000, 100);
122 break;
123 case blink::WebInputEvent::TouchTypeFirst:
124 UMA_HISTOGRAM_CUSTOM_COUNTS(
125 "Event.Latency.Browser.TouchAcked",
126 acked_delta.InMicroseconds(), 1, 1000000, 100);
127 break;
128 default:
129 NOTREACHED();
130 break;
131 }
132 }
133 }
134
135 // LatencyComponents generated in the renderer must have component IDs
136 // provided to them by the browser process. This function adds the correct
137 // component ID where necessary.
138 void AddLatencyInfoComponentIds(LatencyInfo* latency,
139 int64 latency_component_id) {
140 LatencyInfo::LatencyMap new_components;
141 auto lc = latency->latency_components.begin();
142 while (lc != latency->latency_components.end()) {
143 ui::LatencyComponentType component_type = lc->first.first;
144 if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
145 component_type == ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
146 // Generate a new component entry with the correct component ID
147 auto key = std::make_pair(component_type, latency_component_id);
148 new_components[key] = lc->second;
149
150 // Remove the old entry
151 latency->latency_components.erase(lc++);
152 } else {
153 ++lc;
154 }
155 }
156
157 // Add newly generated components into the latency info
158 for (lc = new_components.begin(); lc != new_components.end(); ++lc) {
159 latency->latency_components[lc->first] = lc->second;
160 }
161 }
162
163 } // namespace
164
165 RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker()
166 : last_event_id_(0), latency_component_id_(0), device_scale_factor_(1) {
167 }
168
169 RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {
170 }
171
172 void RenderWidgetHostLatencyTracker::Initialize(int routing_id,
173 int process_id) {
174 DCHECK_EQ(0, last_event_id_);
175 DCHECK_EQ(0, latency_component_id_);
176 last_event_id_ = static_cast<int64>(process_id) << 32;
177 latency_component_id_ = routing_id | last_event_id_;
178 }
179
180 void RenderWidgetHostLatencyTracker::OnInputEvent(
181 const blink::WebInputEvent& event,
182 LatencyInfo* latency) {
183 DCHECK(latency);
184 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
185 latency_component_id_, NULL)) {
186 return;
187 }
188
189 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
190 latency_component_id_, ++last_event_id_);
191 latency->TraceEventType(WebInputEventTraits::GetName(event.type));
192 UpdateLatencyCoordinates(event, device_scale_factor_, latency);
193
194 if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
195 latency->AddLatencyNumber(
196 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
197 latency_component_id_, ++last_event_id_);
198
199 // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
200 // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
201 // So we can track the latency specifically for scroll update events.
202 LatencyInfo::LatencyComponent original_component;
203 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
204 &original_component)) {
205 latency->AddLatencyNumberWithTimestamp(
206 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
207 latency_component_id_, original_component.sequence_number,
208 original_component.event_time, original_component.event_count);
209 }
210 }
211 }
212
213 void RenderWidgetHostLatencyTracker::OnInputEventAck(
214 const blink::WebInputEvent& event,
215 LatencyInfo* latency) {
216 DCHECK(latency);
217
218 // Latency ends when it is acked but does not cause render scheduling.
219 bool rendering_scheduled = latency->FindLatency(
220 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL);
221
222 if (WebInputEvent::isGestureEventType(event.type)) {
223 if (rendering_scheduled) {
224 latency->AddLatencyNumber(
225 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0);
226 // TODO(jdduke): Consider exposing histograms for gesture event types.
227 }
228 return;
229 }
230
231 if (WebInputEvent::isTouchEventType(event.type)) {
232 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
233 if (rendering_scheduled) {
234 latency->AddLatencyNumber(
235 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0);
236 ComputeInputLatencyHistograms(WebInputEvent::TouchTypeFirst,
237 latency_component_id_, *latency);
238 }
239 return;
240 }
241
242 if (event.type == WebInputEvent::MouseWheel) {
243 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
244 if (rendering_scheduled) {
245 latency->AddLatencyNumber(
246 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
247 ComputeInputLatencyHistograms(WebInputEvent::MouseWheel,
248 latency_component_id_, *latency);
249 }
250 return;
251 }
252
253 // TODO(jdduke): Determine if mouse and keyboard events are worth hooking
254 // into LatencyInfo.
255 }
256
257 void RenderWidgetHostLatencyTracker::OnSwapCompositorFrame(
258 std::vector<LatencyInfo>* latencies) {
259 DCHECK(latencies);
260 for (LatencyInfo& latency : *latencies)
261 AddLatencyInfoComponentIds(&latency, latency_component_id_);
262 }
263
264 void RenderWidgetHostLatencyTracker::OnFrameSwapped(
265 const ui::LatencyInfo& latency) {
266 LatencyInfo::LatencyComponent swap_component;
267 if (!latency.FindLatency(
268 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
269 &swap_component)) {
270 return;
271 }
272
273 LatencyInfo::LatencyComponent tab_switch_component;
274 if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, latency_component_id_,
275 &tab_switch_component)) {
276 base::TimeDelta delta =
277 swap_component.event_time - tab_switch_component.event_time;
278 for (size_t i = 0; i < tab_switch_component.event_count; i++) {
279 UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta);
280 }
281 }
282
283 LatencyInfo::LatencyComponent rwh_component;
284 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
285 latency_component_id_, &rwh_component)) {
286 return;
287 }
288
289 LatencyInfo::LatencyComponent original_component;
290 if (latency.FindLatency(
291 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
292 latency_component_id_, &original_component)) {
293 // This UMA metric tracks the time from when the original touch event is
294 // created (averaged if there are multiple) to when the scroll gesture
295 // results in final frame swap.
296 for (size_t i = 0; i < original_component.event_count; i++) {
297 UMA_HISTOGRAM_CUSTOM_COUNTS(
298 "Event.Latency.TouchToScrollUpdateSwap",
299 (swap_component.event_time - original_component.event_time)
300 .InMicroseconds(),
301 1,
302 1000000,
303 100);
304 }
305 }
306 }
307
308 } // namespace content
OLDNEW
« 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