Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented Oct 21, 2024

Fixes flutter/flutter#157108

Right now the DL is always growing by a minimum 4096 bytes at a time. On applications with large display lists, this can lead to hundreds of reallocations as the display list is build, as long as each draw op is small. For example, the framework benchmark long picture scrolling draws many lines, each of which is a pretty small op.

Update the code so that we grow by doubling, with a minimum increment of ~16K

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

Copy link
Contributor

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

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

Worth a shot as this is the same strategy used in the Impeller allocator too.

/// @brief Return the next power of 2.
///
/// If the provided value is a power of 2, returns as is.
uint64_t NextPowerOfTwo(uint64_t x) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This goop can be replaced with std::bit_ceil(x)? I remember I couldn't use it earlier because it was C++ 17 only.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems like this is C++ 20 only

// Next greater multiple of DL_BUILDER_PAGE.
allocated_ = (used_ + size + DL_BUILDER_PAGE) & ~(DL_BUILDER_PAGE - 1);
// Next power of two, up to a limit of DL_BUILDER_MAX_GROWTH. This
// assumes that the requested size to allocate is alwaus less than
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: always

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

template <typename T, typename... Args>
void* DisplayListBuilder::Push(size_t pod, Args&&... args) {
size_t size = SkAlignPtr(sizeof(T) + pod);
FML_CHECK(size < (1 << 24));
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this assertion make sense now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not certain the origin of this check.

Copy link
Contributor

Choose a reason for hiding this comment

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

Me either, it might be a carry over from SkLiteDL days?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lets remove it and see what breaks then :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ooopa. No! I just rememered!

It is necessary because the size field is 24-bits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, I'll add it back when I get back lol

Copy link
Contributor

Choose a reason for hiding this comment

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

It's never fired AFAIK, so maybe this should be the impetus that gets me to rewrite builder to not use the size fields any more and produce the offset vector up front...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AFAIK this check could only fire If I tried to encode something that required allocating more than 1 << 24 bytes right?

@jonahwilliams jonahwilliams requested a review from flar October 22, 2024 15:05
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

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

I'm pretty sure recording a very large drawVertices might overflow the growth code, there should be unit tests where we append very large ops. Things that append arrays to them include:

  • rendering ops that have gradients
  • drawAtlas
  • drawPoints
  • drawVertices (oops, no, just copied by reference now)
  • (check anything that uses the CopyV mechanism that adds more data to the pod)

// assumes that the requested size to allocate is always less than
// kDLBuilderMaxGrowth, which given is over a MB is a reasonable
// assumption.
uint64_t next_size = NextPowerOfTwo(used_ + size);
Copy link
Contributor

Choose a reason for hiding this comment

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

used_ starts at 0, as does allocated_ and the first thing we record is something very small, like 8 bytes. So, we do our first growth to 8 bytes, then 16, then ... when our first growth used to be to 4096.

I think we need both a minimum starting size and a maximum growth size for this...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, we should set a min size to the page size.

// assumption.
uint64_t next_size = NextPowerOfTwo(used_ + size);
uint64_t growth_in_bytes = (next_size - allocated_);
allocated_ += std::min(growth_in_bytes, kDLBuilderMaxGrowth);
Copy link
Contributor

Choose a reason for hiding this comment

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

If we need more than MaxGrowth then we fail here. You can max the "unused" part of the growth to MaxGrowth, but you can't make it less than the amount we need total (used_ + size). Better math is needed here...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, I think I was trying to be too clever. I've changed this code so that we always double, and we first increment by whatever is bigger - required size or page size, where page size is about 16K

@jonahwilliams
Copy link
Contributor Author

I believe you changed drawVertices to not copy into the display list. drawPoints/drawAtlas still embed their data right?

@flar
Copy link
Contributor

flar commented Oct 22, 2024

I believe you changed drawVertices to not copy into the display list. drawPoints/drawAtlas still embed their data right?

Anything that uses CopyV in dl_builder.cc could potentially have a very large size. I didn't double check, that list was off the top of my head...

@jonahwilliams
Copy link
Contributor Author

Confirmed that drawPoints does it, I'll use this to test

@jonahwilliams jonahwilliams changed the title [display_list] grow display list backing store by power of two up to ~1MB. [display_list] grow display list backing store by power of two. Oct 22, 2024
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

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

A nit on the data in the test.

EXPECT_EQ(NextPowerOfTwo(5), 8u);
EXPECT_EQ(NextPowerOfTwo(8), 8u);

EXPECT_EQ(NextPowerOfTwo(16), 16u);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you wanted 7 as the arg here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Or something less than 16 but larger than 8...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

template <typename T, typename... Args>
void* DisplayListBuilder::Push(size_t pod, Args&&... args) {
size_t size = SkAlignPtr(sizeof(T) + pod);
FML_CHECK(size < (1 << 24));
Copy link
Contributor

Choose a reason for hiding this comment

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

Me either, it might be a carry over from SkLiteDL days?

allocated_ = (used_ + size + DL_BUILDER_PAGE) & ~(DL_BUILDER_PAGE - 1);
// Round up the allocated size + used size to the next power of 2, with a
// minimum increment of kDLPageSize.
allocated_ = NextPowerOfTwo(used_ + std::max(size, kDLPageSize));
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 23, 2024
@auto-submit auto-submit bot merged commit ec6e28a into flutter:main Oct 23, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 23, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Oct 23, 2024
flutter/engine@50f6d98...ec6e28a

2024-10-23 jonahwilliams@google.com [display_list] grow display list backing store by power of two. (flutter/engine#56004)
2024-10-23 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from xPbin_33tT-_omeQT... to NxrFCTty8wV4-6Cpl... (flutter/engine#56056)
2024-10-23 skia-flutter-autoroll@skia.org Roll Dart SDK from 20470aaa17be to 2a4b728f6a03 (3 revisions) (flutter/engine#56055)
2024-10-23 robert.ancell@canonical.com Move get_keyboard_state from FlKeyboardViewDelegate to FlKeyboardManager. (flutter/engine#56021)
2024-10-23 robert.ancell@canonical.com Move send_key_event from FlKeyboardViewDelegate to FlKeyboardManager. (flutter/engine#56020)
2024-10-23 bdero@google.com [Flutter GPU] Fix assert failure in createDeviceBufferWithCopy. (flutter/engine#56039)
2024-10-22 skia-flutter-autoroll@skia.org Roll Dart SDK from 8de85635d731 to 20470aaa17be (4 revisions) (flutter/engine#56038)
2024-10-22 ditman@gmail.com [web] Remove old futureToPromise. (flutter/engine#55847)
2024-10-22 737941+loic-sharma@users.noreply.github.com [dart:ui] Improve Clip's docs (flutter/engine#55978)
2024-10-22 jonahwilliams@google.com [Impeller] flush thread local resources during toImage/toImageSync. (flutter/engine#56037)
2024-10-22 kpsroka@users.noreply.github.com [canvaskit] Makes access to CkSurface null-safer (flutter/engine#54895)

Also rolling transitive DEPS:
  fuchsia/sdk/core/linux-amd64 from xPbin_33tT-_ to NxrFCTty8wV4

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC codefu@google.com,zra@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@jonahwilliams
Copy link
Contributor Author

reason for revert: unexpected framework ui thread regression, no performance improvement

@jonahwilliams jonahwilliams added the revert Label used to revert changes in a closed and merged pull request. label Oct 24, 2024
auto-submit bot pushed a commit that referenced this pull request Oct 24, 2024
@auto-submit auto-submit bot removed the revert Label used to revert changes in a closed and merged pull request. label Oct 24, 2024
auto-submit bot added a commit that referenced this pull request Oct 24, 2024
…wo. (#56004)" (#56078)

Reverts: #56004
Initiated by: jonahwilliams
Reason for reverting: unexpected framework ui thread regression, no performance improvement
Original PR Author: jonahwilliams

Reviewed By: {flar, chinmaygarde}

This change reverts the following previous change:
Fixes flutter/flutter#157108

Right now the DL is always growing by a minimum 4096 bytes at a time. On applications with large display lists, this can lead to hundreds of reallocations as the display list is build, as long as each draw op is small. For example, the framework benchmark long picture scrolling draws many lines, each of which is a pretty small op.

Update the code so that we grow by doubling, with a minimum increment of ~16K
M97Chahboun pushed a commit to M97Chahboun/flutter that referenced this pull request Oct 30, 2024
…57453)

flutter/engine@50f6d98...ec6e28a

2024-10-23 jonahwilliams@google.com [display_list] grow display list backing store by power of two. (flutter/engine#56004)
2024-10-23 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from xPbin_33tT-_omeQT... to NxrFCTty8wV4-6Cpl... (flutter/engine#56056)
2024-10-23 skia-flutter-autoroll@skia.org Roll Dart SDK from 20470aaa17be to 2a4b728f6a03 (3 revisions) (flutter/engine#56055)
2024-10-23 robert.ancell@canonical.com Move get_keyboard_state from FlKeyboardViewDelegate to FlKeyboardManager. (flutter/engine#56021)
2024-10-23 robert.ancell@canonical.com Move send_key_event from FlKeyboardViewDelegate to FlKeyboardManager. (flutter/engine#56020)
2024-10-23 bdero@google.com [Flutter GPU] Fix assert failure in createDeviceBufferWithCopy. (flutter/engine#56039)
2024-10-22 skia-flutter-autoroll@skia.org Roll Dart SDK from 8de85635d731 to 20470aaa17be (4 revisions) (flutter/engine#56038)
2024-10-22 ditman@gmail.com [web] Remove old futureToPromise. (flutter/engine#55847)
2024-10-22 737941+loic-sharma@users.noreply.github.com [dart:ui] Improve Clip's docs (flutter/engine#55978)
2024-10-22 jonahwilliams@google.com [Impeller] flush thread local resources during toImage/toImageSync. (flutter/engine#56037)
2024-10-22 kpsroka@users.noreply.github.com [canvaskit] Makes access to CkSurface null-safer (flutter/engine#54895)

Also rolling transitive DEPS:
  fuchsia/sdk/core/linux-amd64 from xPbin_33tT-_ to NxrFCTty8wV4

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC codefu@google.com,zra@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
nick9822 pushed a commit to nick9822/flutter that referenced this pull request Dec 18, 2024
…ter/engine#56004)

Fixes flutter#157108

Right now the DL is always growing by a minimum 4096 bytes at a time. On applications with large display lists, this can lead to hundreds of reallocations as the display list is build, as long as each draw op is small. For example, the framework benchmark long picture scrolling draws many lines, each of which is a pretty small op.

Update the code so that we grow by doubling, with a minimum increment of ~16K
nick9822 pushed a commit to nick9822/flutter that referenced this pull request Dec 18, 2024
…wo. (flutter#56004)" (flutter/engine#56078)

Reverts: flutter/engine#56004
Initiated by: jonahwilliams
Reason for reverting: unexpected framework ui thread regression, no performance improvement
Original PR Author: jonahwilliams

Reviewed By: {flar, chinmaygarde}

This change reverts the following previous change:
Fixes flutter#157108

Right now the DL is always growing by a minimum 4096 bytes at a time. On applications with large display lists, this can lead to hundreds of reallocations as the display list is build, as long as each draw op is small. For example, the framework benchmark long picture scrolling draws many lines, each of which is a pretty small op.

Update the code so that we grow by doubling, with a minimum increment of ~16K
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

autosubmit Merge PR when tree becomes green via auto submit App

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[display list] adjust realloc herustic to grow allocation size faster.

3 participants