-
Notifications
You must be signed in to change notification settings - Fork 29.8k
A benchmark test case for measuring scroll smoothness #61998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A benchmark test case for measuring scroll smoothness #61998
Conversation
|
This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again. |
liyuqian
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what janky_count and average_abs_jerk are with resampleEnabled = true in your local test? I'm expecting them to be close to 0 and thus much smaller than the 60hz-input-59.94hz-display case of average_abs_jerk = 176, average_abs_jerk = 1.48 if our default resamplingOffset was chosen properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The integer milliseconds observed from devices look suspicious to me... Did we lose the precision somewhere in the engine? Even with 60hz input, 16ms or 17ms seem to be sufficiently different from 16.67ms which could make resampling be ~4% off?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My very early work of recording gestures shows that, all touch screen event has timestamp of milliseconds precision. For mouse input in desktop and web Flutter the event timestamp is microsecond. I think you can still find those datas in our 1:1 docs.
I think that's from the OS level, not the engine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apology! I tested it again on iOS and also android devices and lost that pattern. I can't find why in the beginning of my project I found that pattern. I'm removing to integer millisecond part.
|
Local test result on a MOTO G4 is: |
liyuqian
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My very early work of recording gestures shows that, all touch screen event has timestamp of milliseconds precision. For mouse input in desktop and web Flutter the event timestamp is microsecond. I think you can still find those datas in our 1:1 docs.
I think that's from the OS level, not the engine.
Is that an Android specific issue or does iOS also have this issue? (I can't tell from the 1:1 doc.) I would be surprised if Fuchsia is only providing input events with millisecond-precision timestamps. CC @dreveman
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the following lines in the gradle file needed to make the test run, or are they just added to keep this gradle file up to date with other gradle files generated by flutter create with a newer Flutter version?
If these are specific to this test, it might be nice to document why they're needed as it doesn't look to be obvious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's copied from what's in flutter create and is necessary to load e2e plugins. Without this I will get:
Plugin project :e2e not found. Please update settings.gradle.
/Users/minglyu/flutter/dev/benchmarks/complex_layout/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java:4: error: package dev.flutter.plugins.e2e does not exist
import dev.flutter.plugins.e2e.E2EPlugin;
^
/Users/minglyu/flutter/dev/benchmarks/complex_layout/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java:14: error: cannot find symbol
E2EPlugin.registerWith(registry.registrarFor("dev.flutter.plugins.e2e.E2EPlugin"));
^
symbol: variable E2EPlugin
location: class GeneratedPluginRegistrant
2 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 27s
I didn't add comments because it's just updating this to newer version, and newer test cases in dev/benchmarks are already the newer version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How's this 40E3 picked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried 35 and 45 and find the result qualitatively same. I'm expecting it to be a few frame interval. With single frame like 16 or 17ms the result has significant fluctuation in my early test.
|
Adding 59Hz input, the test run locally gives: |
My apology! I tested it again on iOS and also android devices and lost that pattern. I can't find why in the beginning of my project I found that pattern. I'm removing to integer millisecond part. @liyuqian |
liyuqian
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
All other ios based driver tests failed. Now my google account is deactivated, I can't see the test log any more but it's possible the failure is related to the introduction of |
This reverts commit 12b7355.
…r#61998)" (flutter#64883) This reverts commit 12b7355.
…tter#64885)" (flutter#64990) This reverts commit df83398.
Description
We've noticed that even when all frames are built and rasterized fast, we can still get janky scrolling (#19222).
This test is an attempt to catch such behavior, especially due to mismatch of the input frequency and frame refresh rate, which there's an attempt to fix it by #60558
The metric we use to measure the janky behavior here is the absolute value of acceleration (2nd derivative) rather than jerk as suggested in go/tq-smooth-scrolling because the input is completely linear and the expected acceleration should be strictly zero, and observed acceleration is jumping from positive to negative within adjacent frame, meaning mathematically the discrete 3-rd derivative (
f[3] - 3*f[2] + 3*f[1] - f[0]) is not a good approximation of jerk (3-rd derivative) Discrete 2nd derivative (f[2] - 2*f[1] + f[0]) on the other hand is a good measure of how the scrolling deviate away from linear, and given the acceleration should average to zero within two frames, it's also a good approximation for jerk in terms of physics.Related Issues
#19222 and its links.
Tests
This PR is itself a test.
Local test on a Moto G4 gives sample result (90Hz input):
{ "janky_count": 506.0, "average_abs_jerk": 2.0151334129828427 }The 2nd diff of the scroller's offset vs timestamp is:

where if the input event frequency is 60Hz
{ "janky_count": 176.0, "average_abs_jerk": 1.4801657785671627 }The 2nd diff of the scroller's offset vs timestamp is:

Those peaks may come from delayed frame or misalignment of 60Hz input and approximately 60Hz (~59.94Hz) refresh rate.
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.