Skip to content

Conversation

@jollygreenlaser
Copy link

@jollygreenlaser jollygreenlaser commented Jan 1, 2022

Fixes #96005

The old example code laid out every single cell and did visibility checks on each of them. This resulted in poor performance and is not a viable pattern to copy.

This takes inspiration from the official youtube video on this builder form to turn this example into an infinite grid. This also adds this video to the documentation because it's really low in the SEO yet very valuable to understand the builder constructor.

While performance can still be hit (especially in debug mode) it degrades with # of cells on screen, rather than # of cells in total.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • All existing and new tests are passing.

@flutter-dashboard flutter-dashboard bot added d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos documentation c: contributor-productivity Team-specific productivity, code health, technical debt. labels Jan 1, 2022
@jollygreenlaser jollygreenlaser changed the title Update example code for InteractiveViewer.builder Update example code and docs for InteractiveViewer.builder Jan 2, 2022
@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label Jan 2, 2022
@goderbauer
Copy link
Member

Can you fix the analyzer issues please? Also, we have started to add tests for these samples. Can you please add one that covers your change? Thanks!

@jollygreenlaser
Copy link
Author

@goderbauer I fixed the analyzer issues, thanks for pointing that out.

I will add the unit tests as soon as I can. If you have any examples to point me towards it's greatly appreciated, no worries if not I can probably find some. This is my first PR that touches flutter!

@goderbauer goderbauer requested a review from justinmc January 5, 2022 22:32
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning up this example! I should have updated it when I did Lazy Flutter Performance. This looks more useful and easier to understand, I'm on board. Just a few small nits you might want to consider.

LGTM 👍

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot that these examples can be tested now. I'll find you an example.

@justinmc
Copy link
Contributor

justinmc commented Jan 7, 2022

Here's an example of testing an example:

The example: https://github.com/flutter/flutter/blob/master/examples/api/lib/widgets/layout_builder/layout_builder.0.dart
The example's test: https://github.com/flutter/flutter/blob/master/examples/api/test/widgets/layout_builder/layout_builder.0_test.dart

Maybe something like this would make a good test for this example:

  1. Render the example.
  2. Expect there to be a Positioned with "0 x 0".
  3. Expect there to be the correct amount of Positioned widgets.
  4. Expect there to be NO Positioned with "0 x 10".
  5. Use a gesture to pan over to "0 x 10".
  6. Expect that "0 x 0" is gone.
  7. Expect that "0 x 10" is there.
  8. Expect the number of Positioned widgets is the same.

@jollygreenlaser
Copy link
Author

Thanks for all the help! Hopefully this test covers enough.

@jollygreenlaser jollygreenlaser force-pushed the infinite-grid-example branch 2 times, most recently from cdc48cf to 4facbc4 Compare January 8, 2022 21:53
@jollygreenlaser jollygreenlaser marked this pull request as ready for review January 9, 2022 01:06
@jollygreenlaser
Copy link
Author

jollygreenlaser commented Jan 14, 2022

@justinmc I noticed that this still lacks performance when zoomed out and many cells are on screen (this is why I increased the dimensions of each cell).

However, the same # of cells being rendered via the standard child form has no performance issue. My understanding is that this is due to the cells being rebuilt each tick with builder.

I'm pretty new to Flutter and couldn't figure out a way around this. Using the same const cell for every cell didn't make it happy. Read a ton of performance blogs now. Tried reading the source code for how slivers handle this, couldn't quite parse it, going to try again soon.

If you have any thoughts on this or time to help I'd greatly appreciate it. Hoping to be able to use this builder form with the same performance I could get from something like ListView.builder.

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

So sorry this took me forever to re-review, I need to clean out my Github notifications. Thanks for adding the test.

If you want to try to improve the performance of the rebuilding cells, I have 2 ideas. At a glance I think they are being rebuilt every time the InteractiveViewer transformation matrix changes, which is a ton, probably 60 x per second during a pan gesture.

  1. As a quick improvement, consider giving them a key that can uniquely identify them between builds. The widgets will still be rebuilt, but that might allow the underlying RenderObjects/Elements to be reused if I'm correct. Something like ValueKey('$row,$col').
  2. You could try to cache the cell widgets. Any widgets that are being instantiated inside of InteractiveViewer's builder method will be re-instantiated every frame that InteractiveViewer zooms or pans. Doing something fancier there so we only instantiate/dispose the cells when they enter/leave the screen would probably help a lot.

I'll wait to merge this in case you want to take a look at the performance, or that could also be another PR.

@justinmc justinmc requested a review from gspencergoog January 27, 2022 18:22
@justinmc
Copy link
Contributor

@gspencergoog Tagged you for secondary review since this uses your new example testing.

Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

Comment on lines +135 to +137
child: builder(context, row, col)),
],
));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a couple of commas and reformat for better formatting.

Suggested change
child: builder(context, row, col)),
],
));
child: builder(context, row, col),
),
],
),
);

alignment: Alignment.centerLeft,
child: Text('$row x $column'),
),
);
Copy link
Contributor

@gspencergoog gspencergoog Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a comma between the "}" and the ")" on the next line and reformat. It'll cascade nicely then (I know it was like that before, but might was well fix it).

@goderbauer
Copy link
Member

(triage) @AleLazar Can you please fix the two nits so we can submit this? Thanks!

@goderbauer
Copy link
Member

Superseded by #98623.

@goderbauer goderbauer closed this Feb 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: contributor-productivity Team-specific productivity, code health, technical debt. d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Documentation] update InteractiveViewer.builder example to make it more performant

4 participants