Commit 43164af2 authored by Sahel Sharify's avatar Sahel Sharify Committed by Commit Bot

Latency info terminated while scrolling against the scroll extent.

We already skip recording scroll metrics when the GSU events are ignored
since ignored events don't cause GPU swap.
This cl terminates the latency info from ignored GSU events and adds a
unittest to verify the termination. It also has a browsertest to verify
no scroll latency gets recorded when GSU events are ignored.

ScrollLatencyBrowserTest.ScrollLatencyNotRecordedIfGSUIgnored

Bug: 773740
Test: RenderWidgetHostLatencyTrackerTest.LatencyTerminatedOnAckIfGSUIgnored,
Change-Id: Idaa4c3d739a79a8e44e4c3db82a74877428d404c
Reviewed-on: https://chromium-review.googlesource.com/1080035
Commit-Queue: Sahel Sharifymoghaddam <sahel@chromium.org>
Reviewed-by: default avatarTimothy Dresser <tdresser@chromium.org>
Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565069}
parent c160acab
...@@ -226,8 +226,11 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck( ...@@ -226,8 +226,11 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0); latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0);
// If this event couldn't have caused a gesture event, and it didn't trigger // If this event couldn't have caused a gesture event, and it didn't trigger
// rendering, we're done processing it. If the event got coalesced then // rendering, we're done processing it. If the event got coalesced then
// terminate it as well. // terminate it as well. We also exclude cases where we're against the scroll
if (!rendering_scheduled || latency->coalesced()) { // extent from scrolling metrics.
if (!rendering_scheduled || latency->coalesced() ||
(event.GetType() == WebInputEvent::kGestureScrollUpdate &&
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) {
latency->Terminate(); latency->Terminate();
} }
......
...@@ -802,6 +802,33 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ...@@ -802,6 +802,33 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 0)); EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 0));
} }
TEST_F(RenderWidgetHostLatencyTrackerTest, LatencyTerminatedOnAckIfGSUIgnored) {
for (blink::WebGestureDevice source_device :
{blink::kWebGestureDeviceTouchscreen,
blink::kWebGestureDeviceTouchpad}) {
for (bool rendering_on_main : {false, true}) {
auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, source_device);
base::TimeTicks now = base::TimeTicks::Now();
scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency;
scroll_latency.set_source_event_type(
source_device == blink::kWebGestureDeviceTouchscreen
? ui::SourceEventType::TOUCH
: ui::SourceEventType::WHEEL);
scroll_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
tracker()->OnInputEventAck(scroll, &scroll_latency,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_TRUE(scroll_latency.terminated());
}
}
}
TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) { TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_begin = SyntheticWebGestureEventBuilder::BuildScrollBegin( auto scroll_begin = SyntheticWebGestureEventBuilder::BuildScrollBegin(
5, -5, blink::kWebGestureDeviceTouchscreen); 5, -5, blink::kWebGestureDeviceTouchscreen);
......
...@@ -30,7 +30,7 @@ const char kDataURL[] = ...@@ -30,7 +30,7 @@ const char kDataURL[] =
"<!DOCTYPE html>" "<!DOCTYPE html>"
"<html>" "<html>"
"<head>" "<head>"
"<title>Mouse wheel latency histograms reported.</title>" "<title>Scroll latency histograms browsertests.</title>"
"<script src=\"../../resources/testharness.js\"></script>" "<script src=\"../../resources/testharness.js\"></script>"
"<script src=\"../../resources/testharnessreport.js\"></script>" "<script src=\"../../resources/testharnessreport.js\"></script>"
"<style>" "<style>"
...@@ -40,7 +40,20 @@ const char kDataURL[] = ...@@ -40,7 +40,20 @@ const char kDataURL[] =
"</style>" "</style>"
"</head>" "</head>"
"<body>" "<body>"
"<div id='spinner'>Spinning</div>"
"</body>" "</body>"
"<script>"
"var degree = 0;"
"function spin() {"
"degree = degree + 3;"
"if (degree >= 360)"
"degree -= 360;"
"document.getElementById('spinner').style['transform'] = "
"'rotate(' + degree + 'deg)';"
"requestAnimationFrame(spin);"
"}"
"spin();"
"</script>"
"</html>"; "</html>";
} // namespace } // namespace
...@@ -73,6 +86,11 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest { ...@@ -73,6 +86,11 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
frame_observer_->Wait(); frame_observer_->Wait();
} }
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
run_loop_->Quit();
}
protected: protected:
void LoadURL() { void LoadURL() {
const GURL data_url(kDataURL); const GURL data_url(kDataURL);
...@@ -109,9 +127,20 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest { ...@@ -109,9 +127,20 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
GetWidgetHost()->ForwardGestureEvent(event2); GetWidgetHost()->ForwardGestureEvent(event2);
} }
// Returns true if the given histogram has recorded the expected number of
// samples.
bool VerifyRecordedSamplesForHistogram(
const size_t num_samples,
const std::string& histogram_name) const {
return num_samples ==
histogram_tester_.GetAllSamples(histogram_name).size();
}
std::unique_ptr<base::RunLoop> run_loop_;
private: private:
base::HistogramTester histogram_tester_;
base::MessageLoop loop_; base::MessageLoop loop_;
base::RunLoop runner_;
std::unique_ptr<MainThreadFrameObserver> frame_observer_; std::unique_ptr<MainThreadFrameObserver> frame_observer_;
DISALLOW_COPY_AND_ASSIGN(ScrollLatencyBrowserTest); DISALLOW_COPY_AND_ASSIGN(ScrollLatencyBrowserTest);
...@@ -122,20 +151,63 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest { ...@@ -122,20 +151,63 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest, SmoothWheelScroll) { IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest, SmoothWheelScroll) {
LoadURL(); LoadURL();
base::HistogramTester histogram_tester;
DoSmoothWheelScroll(gfx::Vector2d(0, 100)); DoSmoothWheelScroll(gfx::Vector2d(0, 100));
while (!VerifyRecordedSamplesForHistogram(
size_t num_samples = 0; 1, "Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin2")) {
while (num_samples == 0) {
FetchHistogramsFromChildProcesses();
num_samples =
histogram_tester
.GetAllSamples(
"Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin2")
.size();
GiveItSomeTime(); GiveItSomeTime();
FetchHistogramsFromChildProcesses();
} }
} }
// Do an upward wheel scroll, and verify that no scroll metrics is recorded when
// the scroll event is ignored.
IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest,
ScrollLatencyNotRecordedIfGSUIgnored) {
LoadURL();
auto scroll_update_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kGestureScrollUpdate);
// Try to scroll upward, the GSU(s) will get ignored since the scroller is at
// its extent.
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.anchor = gfx::PointF(10, 10);
params.distances.push_back(gfx::Vector2d(0, 60));
run_loop_ = std::make_unique<base::RunLoop>();
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetWidgetHost()->QueueSyntheticGesture(
std::move(gesture),
base::BindOnce(&ScrollLatencyBrowserTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
// Runs until we get the OnSyntheticGestureCompleted callback and verify that
// the first GSU event is ignored.
run_loop_->Run();
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
scroll_update_watcher->GetAckStateWaitIfNecessary());
// Wait for one frame and then verify that the scroll metrics are not
// recorded.
std::unique_ptr<RenderFrameSubmissionObserver> frame_observer =
std::make_unique<RenderFrameSubmissionObserver>(
GetWidgetHost()->render_frame_metadata_provider());
frame_observer->WaitForAnyFrameSubmission();
FetchHistogramsFromChildProcesses();
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.BrowserNotifiedToBeforeGpuSwap2"));
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.GpuSwap2"));
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.HandledToRendererSwap2_Impl"));
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.RendererSwapToBrowserNotified2"));
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.TimeToHandled2_Impl"));
EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
0, "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin2"));
}
} // namespace content } // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment