Skip to content

Calling layout on TextPainter for conditional layouts can be slow #132421

@Dall127

Description

@Dall127

Details

To recreate:

Run TextPainter.layout multiple times, and it gets progressively worse; My main program runs layout a lot to conditionally paint text on a page, and it slowly crawls to a stop. I've provided sample code, and other requested information.

(My hypothesis is that it's compounding the calls to layout and calling every other CKParagragh that exists, but not sure)

  • I ran it on both flutter stable branch and flutter master, both producing the same issue
  • flutter run --profile --trace-skia produced no output
  • flutter analyze produces no issues

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Painting demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int difference = 0;

  StringBuffer buffer = StringBuffer("Hello world");
  TextStyle style = const TextStyle(fontSize: 20, color: Colors.black);
  TextPainter painter = TextPainter(textDirection: TextDirection.ltr);

  void paintMultiple() {
    final startTime = DateTime.now();
    difference = 0;
    for (int i = 0; i < 200; i++) {
      buffer.write("Hello world");
      painter.text = TextSpan(text: buffer.toString(), style: style);
      painter.layout();
    }
    final endTime = DateTime.now();

    setState(() {
      difference = endTime.difference(startTime).inMilliseconds;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title:
              Text(widget.title, style: const TextStyle(color: Colors.white)),
          backgroundColor: Colors.purple,
        ),
        body: Center(
            child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (difference > 0) Text("Time to paint: $difference milliseconds"),
            if (difference == 0) const Text("Time to paint: not painted"),
            const SizedBox(height: 20),
            OutlinedButton(
              onPressed: () => paintMultiple(),
              child: const Text("Paint multiple times"),
            )
          ],
        )));
  }
}

MacOS - Apple M1 Max - 32 GB Ram - Ventura version 13.5 (22G74)
image

Chrome - Version 115.0.5790.170 (Official Build) (arm64)
image

IMG_2193.mov
[redacted]@[redacted] painter_sample % flutter doctor -v
[✓] Flutter (Channel master, 3.14.0-3.0.pre.45, on macOS 13.5 22G74 darwin-arm64, locale en-US)
    • Flutter version 3.14.0-3.0.pre.45 on channel master at /Users/[redacted]/LocalFrameworks/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 36c40e4972 (50 minutes ago), 2023-08-11 18:48:13 -0400
    • Engine revision 5669544866
    • Dart version 3.2.0 (build 3.2.0-62.0.dev)
    • DevTools version 2.26.1

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /Users/[redacted]/Library/Android/sdk
    • Platform android-33, build-tools 32.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E300c
    • CocoaPods version 1.12.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • 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 17.0.6+0-17.0.6b829.9-10027231)

[✓] VS Code (version 1.81.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.70.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.5 22G74 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 115.0.5790.170

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

• No issues found!


Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: typographyText rendering, possibly libtxtc: performanceRelates to speed or footprint issues (see "perf:" labels)engineflutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions