OLD | NEW |
---|---|
(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 "components/latency_tracker/latency_tracker.h" | |
6 | |
7 #include "base/metrics/histogram_functions.h" | |
8 #include "base/metrics/histogram_macros.h" | |
9 | |
10 using ui::LatencyInfo; | |
11 | |
12 // TODO: SHould we have separate classes with state for browser and GPU | |
13 // callbacks? Or perhaps stateless? | |
14 | |
15 namespace latency_tracker { | |
16 namespace { | |
17 | |
18 // Check valid timing for start and end latency components. | |
19 #define CONFIRM_VALID_TIMING(start, end) \ | |
20 DCHECK(!start.first_event_time.is_null()); \ | |
21 DCHECK(!end.last_event_time.is_null()); \ | |
22 DCHECK_GE(end.last_event_time, start.first_event_time); | |
23 | |
24 // Event latency that is mostly under 1 second. We should only use 100 buckets | |
25 // when needed. | |
26 #define UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(name, start, \ | |
27 end) \ | |
28 CONFIRM_VALID_TIMING(start, end) \ | |
29 base::UmaHistogramCustomCounts( \ | |
30 name, (end.last_event_time - start.first_event_time).InMicroseconds(), \ | |
31 1, 1000000, 100); | |
32 | |
33 // Long touch/wheel scroll latency component that is mostly under 200ms. | |
34 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(name, start, end) \ | |
35 CONFIRM_VALID_TIMING(start, end) \ | |
36 base::Histogram::FactoryGet(name, 1000, 200000, 50, \ | |
37 base::HistogramBase::kUmaTargetedHistogramFlag) \ | |
38 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); | |
39 | |
40 // Short touch/wheel scroll latency component that is mostly under 50ms. | |
41 #define UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(name, start, end) \ | |
42 CONFIRM_VALID_TIMING(start, end) \ | |
43 base::Histogram::FactoryGet(name, 1, 50000, 50, \ | |
44 base::HistogramBase::kUmaTargetedHistogramFlag) \ | |
45 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); | |
46 | |
47 std::string LatencySourceEventTypeToInputModalityString( | |
48 ui::SourceEventType type) { | |
49 switch (type) { | |
50 case ui::SourceEventType::WHEEL: | |
51 return "Wheel"; | |
52 case ui::SourceEventType::TOUCH: | |
53 return "Touch"; | |
54 default: | |
55 return ""; | |
56 } | |
57 } | |
58 | |
59 void ComputeScrollLatencyHistograms( | |
60 const LatencyInfo::LatencyComponent& gpu_swap_begin_component, | |
61 const LatencyInfo::LatencyComponent& gpu_swap_end_component, | |
62 const LatencyInfo& latency, | |
63 bool is_running_navigation_hint_task) { | |
64 DCHECK(!latency.coalesced()); | |
65 if (latency.coalesced()) | |
66 return; | |
67 | |
68 DCHECK(!gpu_swap_begin_component.event_time.is_null()); | |
69 DCHECK(!gpu_swap_end_component.event_time.is_null()); | |
70 LatencyInfo::LatencyComponent original_component; | |
71 if (latency.FindLatency( | |
72 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, | |
73 &original_component)) { | |
74 // This UMA metric tracks the time between the final frame swap for the | |
75 // first scroll event in a sequence and the original timestamp of that | |
76 // scroll event's underlying touch event. | |
77 for (size_t i = 0; i < original_component.event_count; i++) { | |
78 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
79 "Event.Latency.TouchToFirstScrollUpdateSwapBegin", | |
80 original_component, gpu_swap_begin_component); | |
81 } | |
82 // TODO(horo): IsRunningNavigationHintTask UMAs are only for | |
83 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when | |
84 // the experimentation finished (crbug.com/638827). | |
85 if (is_running_navigation_hint_task) { | |
86 for (size_t i = 0; i < original_component.event_count; i++) { | |
87 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
88 "Event.Latency.TouchToFirstScrollUpdateSwapBegin_" | |
89 "IsRunningNavigationHintTask", | |
90 original_component, gpu_swap_begin_component); | |
91 } | |
92 } | |
93 } else if (!latency.FindLatency( | |
94 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, | |
95 &original_component)) { | |
96 return; | |
97 } | |
98 | |
99 // This UMA metric tracks the time from when the original touch event is | |
100 // created to when the scroll gesture results in final frame swap. | |
101 for (size_t i = 0; i < original_component.event_count; i++) { | |
102 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
103 "Event.Latency.TouchToScrollUpdateSwapBegin", original_component, | |
104 gpu_swap_begin_component); | |
105 } | |
106 // TODO(horo): IsRunningNavigationHintTask UMAs are only for | |
107 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when | |
108 // the experimentation finished (crbug.com/638827). | |
109 if (is_running_navigation_hint_task) { | |
110 for (size_t i = 0; i < original_component.event_count; i++) { | |
111 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
112 "Event.Latency.TouchToScrollUpdateSwapBegin_" | |
113 "IsRunningNavigationHintTask", | |
114 original_component, gpu_swap_begin_component); | |
115 } | |
116 } | |
117 } | |
118 | |
119 } // namespace | |
120 | |
121 void LatencyTracker::OnGpuSwapBufersCompleted( | |
Fady Samuel
2017/03/23 17:24:37
This should probably be on CompositorFrameActivate
| |
122 const LatencyInfo& latency, | |
123 bool is_running_navigation_hint_task) { | |
124 LOG(ERROR) << "LatencyTracker::OnGpuSwapBufersCompleted"; | |
125 int i = 0; | |
126 for (const auto& lc : latency.latency_components()) { | |
127 ++i; | |
128 LOG(ERROR) << "Component " << i << ": " | |
129 << ui::GetComponentName(lc.first.first); | |
130 } | |
131 | |
132 LatencyInfo::LatencyComponent gpu_swap_end_component; | |
133 if (!latency.FindLatency( | |
134 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, | |
135 &gpu_swap_end_component)) { | |
136 return; | |
137 } | |
138 | |
139 LatencyInfo::LatencyComponent gpu_swap_begin_component; | |
140 if (!latency.FindLatency(ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, | |
141 &gpu_swap_begin_component)) { | |
142 return; | |
143 } | |
144 | |
145 LatencyInfo::LatencyComponent tab_switch_component; | |
146 if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, &tab_switch_component)) { | |
147 base::TimeDelta delta = | |
148 gpu_swap_end_component.event_time - tab_switch_component.event_time; | |
149 for (size_t i = 0; i < tab_switch_component.event_count; i++) { | |
150 UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta); | |
151 } | |
152 } | |
153 | |
154 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, | |
155 nullptr)) { | |
156 return; | |
157 } | |
158 | |
159 ui::SourceEventType source_event_type = latency.source_event_type(); | |
160 if (source_event_type == ui::SourceEventType::WHEEL || | |
161 source_event_type == ui::SourceEventType::TOUCH) { | |
162 ComputeTouchAndWheelScrollLatencyHistograms( | |
163 gpu_swap_begin_component, | |
164 gpu_swap_end_component, latency); | |
165 } | |
166 | |
167 // Compute the old scroll update latency metrics. They are exclusively | |
168 // calculated for touch scrolls, and will be deprecated on M56. | |
169 // (https://crbug.com/649754) | |
170 LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component; | |
171 if (!latency.FindLatency( | |
172 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0, | |
173 &mouse_wheel_scroll_update_component)) { | |
174 ComputeScrollLatencyHistograms( | |
175 gpu_swap_begin_component, gpu_swap_end_component, | |
176 latency, is_running_navigation_hint_task); | |
177 } | |
178 } | |
179 | |
180 void LatencyTracker::ReportRapporScrollLatency( | |
181 const std::string& name, | |
182 const LatencyInfo::LatencyComponent& start_component, | |
183 const LatencyInfo::LatencyComponent& end_component) {} | |
184 | |
185 void LatencyTracker::ComputeTouchAndWheelScrollLatencyHistograms( | |
186 const ui::LatencyInfo::LatencyComponent& gpu_swap_begin_component, | |
187 const ui::LatencyInfo::LatencyComponent& gpu_swap_end_component, | |
188 const ui::LatencyInfo& latency) { | |
189 DCHECK(!latency.coalesced()); | |
190 if (latency.coalesced()) | |
191 return; | |
192 | |
193 LatencyInfo::LatencyComponent original_component; | |
194 std::string scroll_name = "ScrollUpdate"; | |
195 | |
196 const std::string input_modality = | |
197 LatencySourceEventTypeToInputModalityString(latency.source_event_type()); | |
198 | |
199 if (latency.FindLatency( | |
200 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, | |
201 &original_component)) { | |
202 scroll_name = "ScrollBegin"; | |
203 // This UMA metric tracks the time between the final frame swap for the | |
204 // first scroll event in a sequence and the original timestamp of that | |
205 // scroll event's underlying touch/wheel event. | |
206 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
207 "Event.Latency.ScrollBegin." + input_modality + | |
208 ".TimeToScrollUpdateSwapBegin2", | |
209 original_component, gpu_swap_begin_component); | |
210 | |
211 ReportRapporScrollLatency( | |
212 "Event.Latency.ScrollBegin." + input_modality + | |
213 ".TimeToScrollUpdateSwapBegin2", | |
214 original_component, gpu_swap_begin_component); | |
215 | |
216 // TODO(lanwei): Will remove them when M56 is stable, see | |
217 // https://crbug.com/669618. | |
218 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
219 "Event.Latency.ScrollUpdate." + input_modality + | |
220 ".TimeToFirstScrollUpdateSwapBegin2", | |
221 original_component, gpu_swap_begin_component); | |
222 } else if (latency.FindLatency( | |
223 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, | |
224 &original_component)) { | |
225 // This UMA metric tracks the time from when the original touch event is | |
226 // created to when the scroll gesture results in final frame swap. | |
227 // First scroll events are excluded from this metric. | |
228 if (input_modality == "Touch") { | |
229 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( | |
230 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", | |
231 original_component, gpu_swap_begin_component); | |
232 | |
233 ReportRapporScrollLatency( | |
234 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", | |
235 original_component, gpu_swap_begin_component); | |
236 } | |
237 } else { | |
238 // No original component found. | |
239 return; | |
240 } | |
241 | |
242 LatencyInfo::LatencyComponent rendering_scheduled_component; | |
243 bool rendering_scheduled_on_main = latency.FindLatency( | |
244 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, | |
245 &rendering_scheduled_component); | |
246 if (!rendering_scheduled_on_main) { | |
247 if (!latency.FindLatency( | |
248 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, | |
249 &rendering_scheduled_component)) | |
250 return; | |
251 } | |
252 | |
253 const std::string thread_name = rendering_scheduled_on_main ? "Main" : "Impl"; | |
254 | |
255 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( | |
256 "Event.Latency." + scroll_name + "." + input_modality + | |
257 ".TimeToHandled2_" + thread_name, | |
258 original_component, rendering_scheduled_component); | |
259 | |
260 LatencyInfo::LatencyComponent renderer_swap_component; | |
261 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, | |
262 &renderer_swap_component)) | |
263 return; | |
264 | |
265 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( | |
266 "Event.Latency." + scroll_name + "." + input_modality + | |
267 ".HandledToRendererSwap2_" + thread_name, | |
268 rendering_scheduled_component, renderer_swap_component); | |
269 | |
270 LatencyInfo::LatencyComponent browser_received_swap_component; | |
271 if (!latency.FindLatency( | |
272 ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, | |
273 &browser_received_swap_component)) | |
274 return; | |
275 | |
276 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2( | |
277 "Event.Latency." + scroll_name + "." + input_modality + | |
278 ".RendererSwapToBrowserNotified2", | |
279 renderer_swap_component, browser_received_swap_component); | |
280 | |
281 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( | |
282 "Event.Latency." + scroll_name + "." + input_modality + | |
283 ".BrowserNotifiedToBeforeGpuSwap2", | |
284 browser_received_swap_component, gpu_swap_begin_component); | |
285 | |
286 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2( | |
287 "Event.Latency." + scroll_name + "." + input_modality + ".GpuSwap2", | |
288 gpu_swap_begin_component, gpu_swap_end_component); | |
289 } | |
290 } // namespace content | |
OLD | NEW |