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

Side by Side Diff: content/browser/renderer_host/input/render_widget_host_latency_tracker.cc

Issue 2771053003: WIP: Plumbing input event latency reporting through Mus GPU.
Patch Set: Created 3 years, 9 months 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/input/render_widget_host_latency_tracker .h" 5 #include "content/browser/renderer_host/input/render_widget_host_latency_tracker .h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram_functions.h" 10 #include "base/metrics/histogram_functions.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 base::UmaHistogramCustomCounts( \ 90 base::UmaHistogramCustomCounts( \
91 name, (end.last_event_time - start.first_event_time).InMicroseconds(), \ 91 name, (end.last_event_time - start.first_event_time).InMicroseconds(), \
92 1, 1000000, 100); 92 1, 1000000, 100);
93 93
94 #define UMA_HISTOGRAM_INPUT_LATENCY_MILLISECONDS(name, start, end) \ 94 #define UMA_HISTOGRAM_INPUT_LATENCY_MILLISECONDS(name, start, end) \
95 CONFIRM_VALID_TIMING(start, end) \ 95 CONFIRM_VALID_TIMING(start, end) \
96 base::UmaHistogramCustomCounts( \ 96 base::UmaHistogramCustomCounts( \
97 name, (end.last_event_time - start.first_event_time).InMilliseconds(), \ 97 name, (end.last_event_time - start.first_event_time).InMilliseconds(), \
98 1, 1000, 50); 98 1, 1000, 50);
99 99
100 // Touch/wheel to scroll latency using Rappor.
101 #define RAPPOR_TOUCH_WHEEL_TO_SCROLL_LATENCY(delegate, name, start, end) \
102 CONFIRM_VALID_TIMING(start, end) \
103 rappor::RapporService* rappor_service = \
104 GetContentClient()->browser()->GetRapporService(); \
105 if (rappor_service && delegate) { \
106 std::unique_ptr<rappor::Sample> sample = \
107 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); \
108 delegate->AddDomainInfoToRapporSample(sample.get()); \
109 sample->SetUInt64Field( \
110 "Latency", \
111 (end.last_event_time - start.first_event_time).InMicroseconds(), \
112 rappor::NO_NOISE); \
113 rappor_service->RecordSample(name, std::move(sample)); \
114 }
115
116 // Long touch/wheel scroll latency component that is mostly under 200ms. 100 // Long touch/wheel scroll latency component that is mostly under 200ms.
117 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(name, start, end) \ 101 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(name, start, end) \
118 CONFIRM_VALID_TIMING(start, end) \ 102 CONFIRM_VALID_TIMING(start, end) \
119 base::Histogram::FactoryGet(name, 1000, 200000, 50, \ 103 base::Histogram::FactoryGet(name, 1000, 200000, 50, \
120 base::HistogramBase::kUmaTargetedHistogramFlag) \ 104 base::HistogramBase::kUmaTargetedHistogramFlag) \
121 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); 105 ->Add((end.last_event_time - start.first_event_time).InMicroseconds());
122 106
123 // Short touch/wheel scroll latency component that is mostly under 50ms. 107 // Short touch/wheel scroll latency component that is mostly under 50ms.
124 #define UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(name, start, end) \ 108 #define UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(name, start, end) \
125 CONFIRM_VALID_TIMING(start, end) \ 109 CONFIRM_VALID_TIMING(start, end) \
126 base::Histogram::FactoryGet(name, 1, 50000, 50, \ 110 base::Histogram::FactoryGet(name, 1, 50000, 50, \
127 base::HistogramBase::kUmaTargetedHistogramFlag) \ 111 base::HistogramBase::kUmaTargetedHistogramFlag) \
128 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); 112 ->Add((end.last_event_time - start.first_event_time).InMicroseconds());
129 113
130 std::string LatencySourceEventTypeToInputModalityString(
131 ui::SourceEventType type) {
132 switch (type) {
133 case ui::SourceEventType::WHEEL:
134 return "Wheel";
135 case ui::SourceEventType::TOUCH:
136 return "Touch";
137 default:
138 return "";
139 }
140 }
141
142 std::string WebInputEventTypeToInputModalityString(WebInputEvent::Type type) { 114 std::string WebInputEventTypeToInputModalityString(WebInputEvent::Type type) {
143 if (type == blink::WebInputEvent::MouseWheel) { 115 if (type == blink::WebInputEvent::MouseWheel) {
144 return "Wheel"; 116 return "Wheel";
145 } else if (WebInputEvent::isKeyboardEventType(type)) { 117 } else if (WebInputEvent::isKeyboardEventType(type)) {
146 return "Key"; 118 return "Key";
147 } else if (WebInputEvent::isMouseEventType(type)) { 119 } else if (WebInputEvent::isMouseEventType(type)) {
148 return "Mouse"; 120 return "Mouse";
149 } else if (WebInputEvent::isTouchEventType(type)) { 121 } else if (WebInputEvent::isTouchEventType(type)) {
150 return "Touch"; 122 return "Touch";
151 } 123 }
152 return ""; 124 return "";
153 } 125 }
154 126
155 void ComputeScrollLatencyHistograms(
156 const LatencyInfo::LatencyComponent& gpu_swap_begin_component,
157 const LatencyInfo::LatencyComponent& gpu_swap_end_component,
158 int64_t latency_component_id,
159 const LatencyInfo& latency,
160 bool is_running_navigation_hint_task) {
161 DCHECK(!latency.coalesced());
162 if (latency.coalesced())
163 return;
164
165 DCHECK(!gpu_swap_begin_component.event_time.is_null());
166 DCHECK(!gpu_swap_end_component.event_time.is_null());
167 LatencyInfo::LatencyComponent original_component;
168 if (latency.FindLatency(
169 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
170 latency_component_id, &original_component)) {
171 // This UMA metric tracks the time between the final frame swap for the
172 // first scroll event in a sequence and the original timestamp of that
173 // scroll event's underlying touch event.
174 for (size_t i = 0; i < original_component.event_count; i++) {
175 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
176 "Event.Latency.TouchToFirstScrollUpdateSwapBegin",
177 original_component, gpu_swap_begin_component);
178 }
179 // TODO(horo): IsRunningNavigationHintTask UMAs are only for
180 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when
181 // the experimentation finished (crbug.com/638827).
182 if (is_running_navigation_hint_task) {
183 for (size_t i = 0; i < original_component.event_count; i++) {
184 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
185 "Event.Latency.TouchToFirstScrollUpdateSwapBegin_"
186 "IsRunningNavigationHintTask",
187 original_component, gpu_swap_begin_component);
188 }
189 }
190 } else if (!latency.FindLatency(
191 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
192 latency_component_id, &original_component)) {
193 return;
194 }
195
196 // This UMA metric tracks the time from when the original touch event is
197 // created to when the scroll gesture results in final frame swap.
198 for (size_t i = 0; i < original_component.event_count; i++) {
199 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
200 "Event.Latency.TouchToScrollUpdateSwapBegin", original_component,
201 gpu_swap_begin_component);
202 }
203 // TODO(horo): IsRunningNavigationHintTask UMAs are only for
204 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when
205 // the experimentation finished (crbug.com/638827).
206 if (is_running_navigation_hint_task) {
207 for (size_t i = 0; i < original_component.event_count; i++) {
208 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
209 "Event.Latency.TouchToScrollUpdateSwapBegin_"
210 "IsRunningNavigationHintTask",
211 original_component, gpu_swap_begin_component);
212 }
213 }
214 }
215
216 void ComputeTouchAndWheelScrollLatencyHistograms(
217 RenderWidgetHostDelegate* render_widget_host_delegate,
218 const ui::LatencyInfo::LatencyComponent& gpu_swap_begin_component,
219 const ui::LatencyInfo::LatencyComponent& gpu_swap_end_component,
220 int64_t latency_component_id,
221 const ui::LatencyInfo& latency) {
222 DCHECK(!latency.coalesced());
223 if (latency.coalesced())
224 return;
225
226 LatencyInfo::LatencyComponent original_component;
227 std::string scroll_name = "ScrollUpdate";
228
229 const std::string input_modality =
230 LatencySourceEventTypeToInputModalityString(latency.source_event_type());
231
232 if (latency.FindLatency(
233 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
234 latency_component_id, &original_component)) {
235 scroll_name = "ScrollBegin";
236 // This UMA metric tracks the time between the final frame swap for the
237 // first scroll event in a sequence and the original timestamp of that
238 // scroll event's underlying touch/wheel event.
239 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
240 "Event.Latency.ScrollBegin." + input_modality +
241 ".TimeToScrollUpdateSwapBegin2",
242 original_component, gpu_swap_begin_component);
243
244 RAPPOR_TOUCH_WHEEL_TO_SCROLL_LATENCY(
245 render_widget_host_delegate,
246 "Event.Latency.ScrollBegin." + input_modality +
247 ".TimeToScrollUpdateSwapBegin2",
248 original_component, gpu_swap_begin_component);
249
250 // TODO(lanwei): Will remove them when M56 is stable, see
251 // https://crbug.com/669618.
252 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
253 "Event.Latency.ScrollUpdate." + input_modality +
254 ".TimeToFirstScrollUpdateSwapBegin2",
255 original_component, gpu_swap_begin_component);
256 } else if (latency.FindLatency(
257 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
258 latency_component_id, &original_component)) {
259 // This UMA metric tracks the time from when the original touch event is
260 // created to when the scroll gesture results in final frame swap.
261 // First scroll events are excluded from this metric.
262 if (input_modality == "Touch") {
263 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
264 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2",
265 original_component, gpu_swap_begin_component);
266
267 RAPPOR_TOUCH_WHEEL_TO_SCROLL_LATENCY(
268 render_widget_host_delegate,
269 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2",
270 original_component, gpu_swap_begin_component);
271 }
272 } else {
273 // No original component found.
274 return;
275 }
276
277 LatencyInfo::LatencyComponent rendering_scheduled_component;
278 bool rendering_scheduled_on_main = latency.FindLatency(
279 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0,
280 &rendering_scheduled_component);
281 if (!rendering_scheduled_on_main) {
282 if (!latency.FindLatency(
283 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
284 &rendering_scheduled_component))
285 return;
286 }
287
288 const std::string thread_name = rendering_scheduled_on_main ? "Main" : "Impl";
289
290 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
291 "Event.Latency." + scroll_name + "." + input_modality +
292 ".TimeToHandled2_" + thread_name,
293 original_component, rendering_scheduled_component);
294
295 LatencyInfo::LatencyComponent renderer_swap_component;
296 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
297 &renderer_swap_component))
298 return;
299
300 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
301 "Event.Latency." + scroll_name + "." + input_modality +
302 ".HandledToRendererSwap2_" + thread_name,
303 rendering_scheduled_component, renderer_swap_component);
304
305 LatencyInfo::LatencyComponent browser_received_swap_component;
306 if (!latency.FindLatency(
307 ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0,
308 &browser_received_swap_component))
309 return;
310
311 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
312 "Event.Latency." + scroll_name + "." + input_modality +
313 ".RendererSwapToBrowserNotified2",
314 renderer_swap_component, browser_received_swap_component);
315
316 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
317 "Event.Latency." + scroll_name + "." + input_modality +
318 ".BrowserNotifiedToBeforeGpuSwap2",
319 browser_received_swap_component, gpu_swap_begin_component);
320
321 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
322 "Event.Latency." + scroll_name + "." + input_modality + ".GpuSwap2",
323 gpu_swap_begin_component, gpu_swap_end_component);
324 }
325 // LatencyComponents generated in the renderer must have component IDs 127 // LatencyComponents generated in the renderer must have component IDs
326 // provided to them by the browser process. This function adds the correct 128 // provided to them by the browser process. This function adds the correct
327 // component ID where necessary. 129 // component ID where necessary.
328 void AddLatencyInfoComponentIds(LatencyInfo* latency, 130 void AddLatencyInfoComponentIds(LatencyInfo* latency,
329 int64_t latency_component_id) { 131 int64_t latency_component_id) {
330 std::vector<std::pair<ui::LatencyComponentType, int64_t>> new_components_key; 132 std::vector<std::pair<ui::LatencyComponentType, int64_t>> new_components_key;
331 std::vector<LatencyInfo::LatencyComponent> new_components_value; 133 std::vector<LatencyInfo::LatencyComponent> new_components_value;
332 for (const auto& lc : latency->latency_components()) { 134 for (const auto& lc : latency->latency_components()) {
333 ui::LatencyComponentType component_type = lc.first.first; 135 ui::LatencyComponentType component_type = lc.first.first;
334 if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) { 136 if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( 253 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
452 "Event.Latency.Browser." + input_modality + "Acked", rwh_component, 254 "Event.Latency.Browser." + input_modality + "Acked", rwh_component,
453 acked_component); 255 acked_component);
454 } 256 }
455 } 257 }
456 } 258 }
457 259
458 void RenderWidgetHostLatencyTracker::OnInputEvent( 260 void RenderWidgetHostLatencyTracker::OnInputEvent(
459 const blink::WebInputEvent& event, 261 const blink::WebInputEvent& event,
460 LatencyInfo* latency) { 262 LatencyInfo* latency) {
263
461 DCHECK(latency); 264 DCHECK(latency);
462 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 265 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
463 latency_component_id_, NULL)) { 266 latency_component_id_, NULL)) {
464 return; 267 return;
465 } 268 }
466 269
467 if (event.timeStampSeconds() && 270 if (event.timeStampSeconds() &&
468 !latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 271 !latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
469 NULL)) { 272 NULL)) {
470 base::TimeTicks timestamp_now = base::TimeTicks::Now(); 273 base::TimeTicks timestamp_now = base::TimeTicks::Now();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 for (LatencyInfo& latency : *latencies) { 357 for (LatencyInfo& latency : *latencies) {
555 AddLatencyInfoComponentIds(&latency, latency_component_id_); 358 AddLatencyInfoComponentIds(&latency, latency_component_id_);
556 latency.AddLatencyNumber( 359 latency.AddLatencyNumber(
557 ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, 0); 360 ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, 0);
558 } 361 }
559 } 362 }
560 363
561 void RenderWidgetHostLatencyTracker::OnFrameSwapped( 364 void RenderWidgetHostLatencyTracker::OnFrameSwapped(
562 const LatencyInfo& latency, 365 const LatencyInfo& latency,
563 bool is_running_navigation_hint_task) { 366 bool is_running_navigation_hint_task) {
564 LatencyInfo::LatencyComponent gpu_swap_end_component; 367 OnGpuSwapBufersCompleted(latency, is_running_navigation_hint_task);
565 if (!latency.FindLatency(
566 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
567 &gpu_swap_end_component)) {
568 return;
569 }
570 368
571 LatencyInfo::LatencyComponent gpu_swap_begin_component;
572 if (!latency.FindLatency(ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
573 &gpu_swap_begin_component)) {
574 return;
575 }
576
577 LatencyInfo::LatencyComponent tab_switch_component;
578 if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, latency_component_id_,
579 &tab_switch_component)) {
580 base::TimeDelta delta =
581 gpu_swap_end_component.event_time - tab_switch_component.event_time;
582 for (size_t i = 0; i < tab_switch_component.event_count; i++) {
583 UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta);
584 }
585 }
586
587 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
588 latency_component_id_, nullptr)) {
589 return;
590 }
591
592 ui::SourceEventType source_event_type = latency.source_event_type();
593 if (source_event_type == ui::SourceEventType::WHEEL ||
594 source_event_type == ui::SourceEventType::TOUCH) {
595 ComputeTouchAndWheelScrollLatencyHistograms(
596 render_widget_host_delegate_, gpu_swap_begin_component,
597 gpu_swap_end_component, latency_component_id_, latency);
598 }
599
600 // Compute the old scroll update latency metrics. They are exclusively
601 // calculated for touch scrolls, and will be deprecated on M56.
602 // (https://crbug.com/649754)
603 LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component;
604 if (!latency.FindLatency(
605 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
606 &mouse_wheel_scroll_update_component)) {
607 ComputeScrollLatencyHistograms(
608 gpu_swap_begin_component, gpu_swap_end_component, latency_component_id_,
609 latency, is_running_navigation_hint_task);
610 }
611 } 369 }
612 370
613 void RenderWidgetHostLatencyTracker::SetDelegate( 371 void RenderWidgetHostLatencyTracker::SetDelegate(
614 RenderWidgetHostDelegate* delegate) { 372 RenderWidgetHostDelegate* delegate) {
615 render_widget_host_delegate_ = delegate; 373 render_widget_host_delegate_ = delegate;
616 } 374 }
617 375
376 void RenderWidgetHostLatencyTracker::ReportRapporScrollLatency(
377 const std::string& name,
378 const LatencyInfo::LatencyComponent& start_component,
379 const LatencyInfo::LatencyComponent& end_component) {
380 CONFIRM_VALID_TIMING(start_component, end_component)
381 rappor::RapporService* rappor_service =
382 GetContentClient()->browser()->GetRapporService();
383 if (rappor_service && render_widget_host_delegate_) {
384 std::unique_ptr<rappor::Sample> sample =
385 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE);
386 render_widget_host_delegate_->AddDomainInfoToRapporSample(sample.get());
387 sample->SetUInt64Field(
388 "Latency",
389 (end_component.last_event_time - start_component.first_event_time).InMic roseconds(),
390 rappor::NO_NOISE);
391 rappor_service->RecordSample(name, std::move(sample));
392 }
393 }
394
618 } // namespace content 395 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698