flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.23k stars 27.26k forks source link

[iOS, web] Slow scrolling. Not real 120Hz #117714

Open nickolasdzemian opened 1 year ago

nickolasdzemian commented 1 year ago

Details

Running web app in release mode on iOS is very slow. It seems there're no real 120fps. On Android everything is okay. Canvas flag or any other improvements haven't any effect.

Target Platform: web Target OS version/browser: iOS 16.2/Chrome 108.0.5359.112 Devices: iPhone 13 Pro Max

Code & Logs

Code ```dart import 'package:flutter/material.dart'; class RegPage extends StatefulWidget { const RegPage({super.key}); @override State createState() => _RegPage(); } class _RegPage extends State with WidgetsBindingObserver { List items = List.generate( 1000, (i) => i % 6 == 0 ? HeadingItem('Heading $i') : MessageItem('Sender $i', i.toString()), ); @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: null, body: ListView.builder( primary: false, scrollDirection: Axis.vertical, shrinkWrap: true, itemExtent: 80, itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return ListTile( title: item.buildTitle(context), subtitle: item.buildSubtitle(context), ); }, ), ); } } abstract class ListItem { Widget buildTitle(BuildContext context); Widget buildSubtitle(BuildContext context); } class HeadingItem implements ListItem { final String heading; HeadingItem(this.heading); @override Widget buildTitle(BuildContext context) { return Text( heading, style: Theme.of(context).textTheme.headline5, ); } @override Widget buildSubtitle(BuildContext context) => const SizedBox.shrink(); } class MessageItem implements ListItem { final String sender; final String uri; MessageItem(this.sender, this.uri); @override Widget buildTitle(BuildContext context) => Text(sender); @override Widget buildSubtitle(BuildContext context) => Image.network('https://picsum.photos/250?image=$uri'); } ``` ``` Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.3.10, on macOS 13.1 22C65 darwin-arm, locale ru-FR) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 14.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.3) [✓] VS Code (version 1.74.2) [✓] Connected device (2 available) [✓] HTTP Host Availability • No issues found! ```
huycozy commented 1 year ago

@nickolasdzemian I'm verifying on Safari, iPhone 7, iOS 15.7.2 but it seems to be fine with me.

Demo https://user-images.githubusercontent.com/104349824/209783256-092b169e-3a73-4b97-aaa1-baf7f0542e5c.MP4

Can you share the tool/method that you are using to measure this on iOS web browser?

nickolasdzemian commented 1 year ago

@nickolasdzemian I'm verifying on Safari, iPhone 7, iOS 15.7.2 but it seems to be fine with me.

Demo Can you share the tool/method that you are using to measure this on iOS web browser?

The measurements are okey. Screen recorder doesn't capture such fps. You can reproduce the issue and see the difference if you open any website and this sample together at real device with 120Hz support (iPhone 13 and above). The problem persists with any scroll component.

huycozy commented 1 year ago

Unfortunately, I don't have a such device. However, in order to the issue can be thoroughly investigated, please provide more information on how you measure "slow scrolling", and adding a video demonstration would also be helpful.

nickolasdzemian commented 1 year ago

Unfortunately, I don't have a such device. However, in order to the issue can be thoroughly investigated, please provide more information on how you measure "slow scrolling", and adding a video demonstration would also be helpful.

For ex, we can use this lib to display fps. The same results with manually counting via plain JS injection.

See attachments below (android is 90, iOS is 60 (browser independent): https://user-images.githubusercontent.com/62357694/209861383-0e9b8962-324f-4c52-9681-76cd16ee0a56.mp4 https://user-images.githubusercontent.com/62357694/209861387-64ea4954-4357-429e-9b7f-5b19f8cab947.MP4
huycozy commented 1 year ago

@nickolasdzemian Thanks for providing the recorded video. Labeling this issue for further investigation from the team.

jmagman commented 1 year ago

cc @yjbanov

ditman commented 1 year ago

@nickolasdzemian does your browser reach 120hz in other, non-flutter web sites?

For example this is a good test for fps: https://testufo.com

Flutter Web does not have any FPS cap, so it'll send frames to your screen as fast as your browser is able to paint them.

nickolasdzemian commented 1 year ago

@nickolasdzemian does your browser reach 120hz in other, non-flutter web sites?

For example this is a good test for fps: https://testufo.com

Flutter Web does not have any FPS cap, so it'll send frames to your screen as fast as your browser is able to paint them.

At test you mentioned above my browser shows 60-60. But I don't understand why non-flutter web sites have a smooth scrolling and a simple flutter app in web is so laggy even without images, only text list. I really see the difference.

ditman commented 1 year ago

I don't understand why non-flutter web sites have a smooth scrolling and a simple flutter app in web is so laggy

The technical reason for this is that "normal" websites use the native scrolling of the browser, but Flutter Web translates the user gestures (scroll/fling) into instructions to repaint the visible pixels of the screen. The browser does not actually scroll anything. (I'm sure there's many tricks the browser is doing to make the native scrolling feel "smoother" that Flutter cannot use!)

Some thing you can test is to try and change the "Platform Mechanics" of the web app to match something that feels more natural to you? The Flutter Gallery, has a selector that lets you test different behaviors:

See screenshot 📱 ![Simulator Screen Shot - iPhone SE (2nd generation) - 2022-12-29 at 17 58 02](https://user-images.githubusercontent.com/1255594/210027031-c5c51d12-3992-426c-9d51-a63457f4977c.png)

There's a very interesting section of the flutter.dev site that talks specifically about this, and how "difficult to describe verbally" it is :)

maRci002 commented 1 year ago

Once flutter able to compile to WASM the performance should be much faster (close to native application).

Here is the proposal: #41062 (it is no more in proposal state since Flutter team working on it, just check out this Twitter post from Flutter's Product Manager)

Technically it can compile to WASM since #117075 PR (currently only on master)

However we should wait for #114244 to enable flutter tools for WASM and there are multiple other issues like icon tree shaking.

mdebbar commented 1 year ago

FYI, https://github.com/flutter/engine/pull/38640 landed in Flutter's main branch a couple days ago. It might help with performance issues on iOS. Could you please give it a shot, @nickolasdzemian?

nickolasdzemian commented 1 year ago

FYI, flutter/engine#38640 landed in Flutter's main branch a couple days ago. It might help with performance issues on iOS. Could you please give it a shot, @nickolasdzemian?

The same behavior. When I turning off 120Hz it runs much better, but at 60Hz I see junking animation. In profiling and other everything is good.

toyoshin5 commented 3 months ago

I believe Flutter iOS already supports 120Hz. However, Flutter Web still runs at only 60fps. Do you know how to make the application run at 120fps on Safari? Both macOS and iOS Safari only run at 60fps. Regular websites run at 120fps.

I have confirmed the following:

The Flutter version is 3.22.

toyoshin5 commented 3 months ago

According to the following website, Safari on the iPhone 15 Pro seems to only support 60fps:

https://testufo.com

It is likely that Safari supports up to 120fps for the scroll frame rate only, while the rendering frame rate is limited to 60fps.

Since Flutter performs scrolling on Canvas, would it be difficult to resolve this issue?

CoocooFroggy commented 3 months ago

As of iOS 18 beta 2, it seems 120fps is now possible.

https://www.reddit.com/r/iOSBeta/comments/1dnkxlx/ios_18_db2_safari_on_iphone_pro_13_now_supports/

toyoshin5 commented 3 months ago

Are you sure? It's really good news. I hope someone tries Flutter Web on iOS 18 beta2

Note: You must turn off the “prefer page rendering updates near 60fps” feature flag.

Settings-Apps-Safari-Advanced-Feature Flags-Turn prefer page rendering updates near 60fps off.

This is only on iOS 18.0 dev beta 2, not iOS 17.6 beta, 18.0 dev beta 1, or anything earlier.

CoocooFroggy commented 3 months ago

iOS 18 will be released in the fall. I wonder if this will work with Flutter out of the box or if Flutter will need to make changes. If anyone has a device on the beta, we would appreciate you trying out a Flutter web application following the steps listed by @toyoshin5 and reporting back!

ditman commented 3 months ago

AT LAST! This is great news, thanks for bringing it up!


From the Reddit comment:

You must turn off the “prefer page rendering updates near 60fps” feature flag.

If it's hidden behind a feature flag, then it's not generally available. Most users won't be flipping about://config stuff to get features; I hope this gets enabled by default at some point during the beta!

Also this only works on iPhone Pros, 13 Pro or newer.

@toyoshin5 This bit is also important! apparently only on iPhone Pros in iOS 18 dev beta 2+.


I wonder if this will work with Flutter out of the box or if Flutter will need to make changes.

@CoocooFroggy Flutter renders at the max FPS allowed by the browser as long as there are frames to render, no changes should be needed in Flutter to take advantage of this.

If anyone has a device on the beta, we would appreciate you trying out a Flutter web application following the steps listed by @toyoshin5 and reporting back!

I have a 15 Pro ready to go, but it's my personal device so I won't update until actual user betas start surfacing :)

CoocooFroggy commented 3 months ago

@ditman I believe it only works on the pro model phones because those are the only iPhones with 120hz screens haha. So not a software limitation to my knowledge 🙃

ditman commented 3 months ago

@ditman I believe it only works on the pro model phones because those are the only iPhones with 120hz screens haha. So not a software limitation to my knowledge 🙃

@CoocooFroggy lol, makes sense! (that won't stop people from complaining on non-pro phones that flutter is "capped at 60fps" 😢)