Repository: flutter
Issue: When one frame takes longer than the frame duration, the next VSync signal will be missed, resulting in a low frame rate
Labels: platform-android,platform-ios,engine,c: performance,customer: alibaba,perf: speed,P2,team-engine,triaged-engine

Let us imagine such a scenario, assuming a complex flutter list page is scrolling or doing animation, and each frame on UI Task Runner takes 17ms. Theoretically, the FPS should be above 55 in this case, but in reality the FPS is 30. The reason is that currently we only wait for the Vsync signal after completing all work of one frame, but since this frame has exceeded 16.6ms, we have missed the next Vsync signal and can only wait for the next one to arrive. 

The following is a sample I wrote to verify this problem, this example will show how many times the widget is refreshed in about 5 seconds (not exact).

In addition, in order to simulate the time-consuming operation, I put the widget to sleep for a few milliseconds during the construction process. The following is the conclusion of my experiment. 


Current implementation of flutter：
|     | refresh count  | FPS |
|  ----  | ----  | ---- |
|  no sleep   |  301  |  60 |
| sleep 17ms  | 151 | 30 |

After patching https://github.com/flutter/engine/pull/29276
|     | refresh count  | FPS |
|  ----  | ----  | ---- |
|  no sleep   |  301  |  60 |
| sleep 17ms  | 251 | 50 |

device:  Huawei P40 Pro , ELS AN00 (mobile) • UQG5T20413009690 • android-arm64  • Android 10 (API 29)

sample code

``` dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HighRefreshPage(),
    );
  }
}

class HighRefreshPage extends StatefulWidget {
  const HighRefreshPage({Key? key}) : super(key: key);

  @override
  _HighRefreshPageState createState() => _HighRefreshPageState();
}

class _HighRefreshPageState extends State<HighRefreshPage> {
  int index = 0;
  int startTimeDelta = 500 * 1000;
  int endTimeDelta = 5500 * 1000;
  int startTimeMicros = -1;

  late Ticker ticker;
  late Color color = Colors.blue;
  @override
  void initState() {
    ticker = Ticker((_){
      if (startTimeMicros == -1) {
        startTimeMicros = DateTime.now().microsecondsSinceEpoch;
        return;
      }

      int now = DateTime.now().microsecondsSinceEpoch;
      if (now - startTimeMicros <= startTimeDelta) {
        return;
      }

      if (now - startTimeMicros >= endTimeDelta) {
        ticker.stop();
        return;
      }

      setState(() {
        index ++;
      });
    });
    ticker.start();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    sleep(const Duration(milliseconds:17));
    return Scaffold(
        backgroundColor: color,
        body: Center(
          child: Text(index.toString(), style: const TextStyle(fontSize: 30, color: Colors.white) ),
        ));
  }
}

```

flutter doctor -v

```
MacBook-Pro:test_driver haoan$ flutter doctor -v
[✓] Flutter (Channel master, 2.6.0-12.0.pre.405, on macOS 11.5.2 20G95 darwin-x64, locale zh-Hans-CN)
    • Flutter version 2.6.0-12.0.pre.405 at /Users/haoan/Develop/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f80d1d9447 (33 hours ago), 2021-10-19 23:33:03 -0400
    • Engine revision e6a4610ebd
    • Dart version 2.15.0 (build 2.15.0-233.0.dev)

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/haoan/Library/Android/sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[!] Xcode - develop for iOS and macOS (Xcode 12.5)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    ! Flutter recommends a minimum Xcode version of 13.0.0.
      Download the latest version or update via the Mac App Store.
    • CocoaPods version 1.10.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 51.0.1
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] IntelliJ IDEA Community Edition (version 2017.3.3)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.60.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.27.0

[✓] Connected device (2 available)
    • ELS AN00 (mobile) • UQG5T20413009690 • android-arm64  • Android 10 (API 29)
    • Chrome (web)      • chrome           • web-javascript • Google Chrome 94.0.4606.81

! Doctor found issues in 2 categories.
```

/cc @chinmaygarde @dnfield @iskakaushik