Skip to content

HtmlElementViews are extremely slow on large screens on Flutter web #146437

@dmosdallas

Description

@dmosdallas

Steps to reproduce

  1. Create a new project,
  2. In main, draw a listview of htmlelementviews (the rendered element doesn't seem to matter.
  3. Scroll when the window is small (kind of a fuzzy number, let's say < 800x600) -- see that performance is pretty decent, independent of the number of elements on screen
  4. Resize the the window to full screen -- performance is now terrible.

I've seen mention in other issues here that the rendering performance of an HtmlElementView is a function of the screen size -- looking at the dom, these widgets seem to be making a full-screen canvas and a hierarchy of clip regions to place the widget correctly.

I've found other (closed) issues related to this topic (e.g., #86868), but don't know of any active work here.

Actual bug

The part here that I believe to be an actual issue is that having these elements present anywhere on the screen, causes everything on the screen to be slow, even when the htmlelementviews are not being rebuilt. For example, add a button to the side of the list of htmlelementviews from the repro example above and the button's hover animation skips frames even when nothing is interacting with the htmlelementview.

In flutter, I generally expect the cost of drawing a new frame to be a function of the subtree that needs to be redrawn, so I find this spooky-action-at-a-distance to be surprising.

Code sample

Code sample
import 'dart:math';

import 'package:flutter/material.dart';
import 'dart:ui_web' as ui_web;
import 'package:web/web.dart' as web;

void main() async {
  runApp(const HtmlWidgetExample());
}

class HtmlWidgetExample extends StatelessWidget {
  const HtmlWidgetExample({super.key});

  @override
  Widget build(BuildContext context) {
    final children = <Widget>[];
    for (int i = 0; i < 50; i++) {
      children.add(DecoratedBox(
        decoration: BoxDecoration(border: Border.all(color: Colors.black)),
        child: HtmlWidget(
          width: 100,
          height: 100,
        ),
      ));
      children.add(const SizedBox(
        height: 8,
      ));
    }
    return MaterialApp(
      title: 'Html Widget Example',
      home: Center(
        child: ListView(
          children: children,
        ),
      ),
    );
  }
}

class HtmlWidget extends StatefulWidget {
  const HtmlWidget({
    this.width = 100,
    this.height = 100,
  });

  final int height;
  final int width;

  @override
  State<StatefulWidget> createState() => _HtmlWidgetState();
}

class _HtmlWidgetState extends State<HtmlWidget> {
  final _element = (web.document.createElement('p') as web.HTMLParagraphElement)
    ..id = _generateId()
    ..innerText = 'Hello';

  static final _random = Random();
  static String _generateId({final int len = 10}) {
    const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz';
    return List.generate(len, (index) => _chars[_random.nextInt(_chars.length)])
        .join();
  }

  _HtmlWidgetState();

  @override
  void initState() {
    super.initState();

    _element.style.width = '${widget.width}px';
    _element.style.height = '${widget.height}px';

    ui_web.platformViewRegistry
        .registerViewFactory(_element.id, (_) => _element);
  }

  @override
  Widget build(BuildContext context) => SizedBox(
        width: widget.width.toDouble(),
        height: widget.height.toDouble(),
        child: HtmlElementView(
          key: Key(_element.id),
          viewType: _element.id,
        ),
      );
}

Performance profiling on master channel

  • The issue still persists on the master channel

Timeline Traces

Timeline Traces JSON
[Paste the Timeline Traces here]

Video demonstration

Video demonstration

[Upload media here]

What target platforms are you seeing this bug on?

Web

OS/Browser name and version | Device information

OS: Reproducible across all major OS versions (tested in MacOS, Windows 11, and Ubuntu 22.04)
Browser: Chrome Version 123.0.6312.107 (Official Build) (x86_64)

Does the problem occur on emulator/simulator as well as on physical devices?

No

Is the problem only reproducible with Impeller?

No

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
$ flutter doctor -v
[✓] Flutter (Channel stable, 3.19.5, on Ubuntu 22.04.4 LTS 6.5.0-26-generic, locale en_US.UTF-8)
    • Flutter version 3.19.5 on channel stable at /home/dallas/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 300451adae (12 days ago), 2024-03-27 21:54:07 -0500
    • Engine revision e76c956498
    • Dart version 3.3.3
    • DevTools version 2.31.1

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /home/dallas/android
    • Platform android-32, build-tools 32.0.0
    • ANDROID_SDK_ROOT = /home/dallas/android
    • Java binary at: /opt/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • Ubuntu clang version 14.0.0-1ubuntu1.1
    • cmake version 3.22.1
    • ninja version 1.10.1
    • pkg-config version 0.29.2

[✓] Android Studio (version 2021.2)
    • Android Studio at /opt/android-studio
    • 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.12+0-b1504.28-7817840)

[✓] VS Code (version 1.88.0)
    • VS Code at /snap/code/current/usr/share/code
    • Flutter extension version 3.82.0

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Ubuntu 22.04.4 LTS 6.5.0-26-generic
    • Chrome (web)    • chrome • web-javascript • Google Chrome 123.0.6312.105

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: platform-viewsEmbedding Android/iOS views in Flutter appsc: performanceRelates to speed or footprint issues (see "perf:" labels)found in release: 3.19Found to occur in 3.19found in release: 3.22Found to occur in 3.22has reproducible stepsThe issue has been confirmed reproducible and is ready to work onperf: speedPerformance issues related to (mostly rendering) speedplatform-webWeb applications specificallyr: duplicateIssue is closed as a duplicate of an existing issueteam-webOwned by Web platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions