funwithflutter / flutter_confetti

A Flutter widget that shoots confetti all over the screen.
https://pub.dev/packages/confetti
MIT License
439 stars 79 forks source link

Severe performance issue on MacOS chrome #66

Open maheshj01 opened 2 years ago

maheshj01 commented 2 years ago

This is very likely a bug in chrome, I am not sure where to report it so I am reporting it here

chrome version

image

This issue is only on the macOS version of chrome and works fine on Windows and Linux.

code sample ```dart import 'package:confetti/confetti.dart'; import 'package:flutter/material.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 MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } final confettiController = ConfettiController(); @override Widget build(BuildContext context) { final screenSize = MediaQuery.of(context).size; return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Stack( fit: StackFit.expand, children: [ SizedBox( height: 50, width: 100, child: ElevatedButton( onPressed: () { confettiController.play(); }, child: Text('tap me')), ), Positioned( top: -100, left: screenSize.width / 2, child: ConfettiWidget( confettiController: confettiController, blastDirection: 0, blastDirectionality: BlastDirectionality.explosive, particleDrag: 0.05, emissionFrequency: 0.5, minimumSize: const Size(10, 10), maximumSize: const Size(50, 50), numberOfParticles: 5, gravity: 0.2, ), ), ], ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } ```

Output comparison chrome vs Firefox on a mac m1

https://user-images.githubusercontent.com/31410839/171102525-95506b14-2a51-48ed-8747-f69caa7727b4.mp4

flutter doctor -v (mac) ``` [✓] Flutter (Channel stable, 3.0.1, on macOS 12.3 21E230 darwin-arm, locale en-IN) • Flutter version 3.0.1 at /Users/mahesh/Documents/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision fb57da5f94 (3 days ago), 2022-05-19 15:50:29 -0700 • Engine revision caaafc5604 • Dart version 2.17.1 • DevTools version 2.12.2 [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) • Android SDK at /Users/mahesh/Library/Android/sdk • Platform android-32, build-tools 31.0.0 • ANDROID_HOME = /Users/mahesh/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763) • All Android licenses accepted. [!] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer ! CocoaPods 1.10.2 out of date (1.11.0 is recommended). CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side. Without CocoaPods, plugins will not work on iOS or macOS. For more info, see https://flutter.dev/platform-plugins To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions. [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2021.1) • Android Studio at /Applications/Android Studio.app/Contents • 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 • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763) [✓] IntelliJ IDEA Community Edition (version 2021.2.1) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin version 61.2.4 • Dart plugin version 212.5080.8 [✓] VS Code (version 1.66.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.40.0 [✓] Connected device (4 available) • Redmi K20 Pro (mobile) • 192.168.1.2:5555 • android-arm64 • Android 11 (API 30) • iPhone 12 Pro (mobile) • 19FD0231-BFF0-441D-B584-AD94C4084525 • ios • com.apple.CoreSimulator.SimRuntime.iOS-15-2 (simulator) • macOS (desktop) • macos • darwin-arm64 • macOS 12.3 21E230 darwin-arm • Chrome (web) • chrome • web-javascript • Google Chrome 101.0.4951.64 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. ```
maheshj01 commented 2 years ago

Heres a deployed app to verify https://chromebug.netlify.app/

HayesGordon commented 2 years ago

Hi @maheshmnj, thanks for bringing this to my attention. I can confirm that I'm experiencing the same issue. Definitely a problem with Chrome and CanvasKit. Here's an old build I have that used to run fine on chrome: https://funwithflutter.github.io/confetti/#/

We will need to report this on Flutter's repo, or potentially Skia.

funwithflutter commented 2 years ago

Hi @maheshmnj any update on this issue?

maheshj01 commented 2 years ago

@funwithflutter This is a bug in the Chrome browser currently being tracked here https://bugs.chromium.org/p/chromium/issues/detail?id=1330463. Let's hope the chrome team fixes it soon.

HayesGordon commented 1 year ago

@maheshmnj it seems like part of the issue is with the native use of Path on Chrome.

In the confetti package a square path is drawn:

final pathShape = Path()
      ..moveTo(0, 0)
      ..lineTo(-size.width, 0)
      ..lineTo(-size.width, size.height)
      ..lineTo(0, size.height)
      ..close();

And later the path is transformed:

final rotationMatrix4 = Matrix4.identity()
        ..translate(particle.location.dx, particle.location.dy)
        ..rotateX(particle.angleX)
        ..rotateY(particle.angleY)
        ..rotateZ(particle.angleZ);

      final finalPath = particle.path.transform(rotationMatrix4.storage);
      canvas.drawPath(finalPath, _particlePaint..color = particle.color);

The call to .transform is a native call.

void _transform(Path outPath, Float64List matrix4) native 'Path_transform';

What is interesting is if you introduce more points to the Path the problem goes away.

final pathShape = Path()
  ..moveTo(0, 0)
  ..lineTo(-size.width, 0)
  ..lineTo(-size.width, size.height)
  ..lineTo(0, size.height)

  // INTRODUCE MORE POINTS
  ..lineTo(0, 0)
  ..lineTo(-size.width, 0)
  ..lineTo(-size.width, size.height)
  ..lineTo(0, size.height)
  //

  ..close();

This can also be observed in the sample, where the stars' confetti (with more path points) does not cause an issue, but the square paths do.

HayesGordon commented 1 year ago

Not closing this issue for now, as the underlying problem has not gone away. I've only added additional path points when the target is web to prevent the above for the Confetti package.