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

Conversation

@gaaclarke
Copy link
Member

@gaaclarke gaaclarke commented Aug 21, 2023

Recycles command buffers instead of deleting them when they are done being used.

@jonahwilliams profiled the Gallery on the Pixel 7 pro and saw that sometimes RenderPassVK::OnEncodeCommands takes a long time in flutter/flutter#132690. After adding adding more tracing it was found that the culprit was deleting the CommandBuffers on the raster thread. This PR removes the deletion of the CommandBuffers and instead resets and recycles them.

unnamed

where GARBO2 is

void CommandPoolVK::GarbageCollectBuffersIfAble() {
  TRACE_EVENT0("impeller", "CommandPoolVK::GARBO2");
   if (std::this_thread::get_id() != owner_id_) {    
     return;  
   }
   buffers_to_collect_.clear();
}

This approach matches the guidances from "Vulkan Best Practice for Mobile Developers" where it is preferable to recycle command buffers than delete them. Also, the recommendation is that if you are not reusing command buffers that you should periodically reset the pool, which we weren't doing.

issue: flutter/flutter#132690

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 and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@gaaclarke gaaclarke force-pushed the recycle-command-buffers-2 branch 2 times, most recently from 843427c to 88fe3bc Compare August 21, 2023 18:01

// This number comes from observing the recycled_buffers_ size while running
// Wonderous and seeing it cap out at 7.
static constexpr size_t kMaxRecycledBufferSize = 10;
Copy link
Member Author

Choose a reason for hiding this comment

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

This may be moot since they will still probably live in the pool.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure this is necessary since like you mention, its the pool itself that has memory. reseting/freeing should be more or less the same right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea, kMaxRecycledBufferSize isn't going to really work because it seems like the pool should be holding onto the command buffers anyways. I removed it.

@gaaclarke gaaclarke marked this pull request as ready for review August 21, 2023 18:16
@gaaclarke gaaclarke marked this pull request as draft August 21, 2023 18:16
@gaaclarke gaaclarke marked this pull request as ready for review August 21, 2023 18:22
break;
}
buffer->reset();
recycled_buffers_.emplace_back(std::move(buffer));
Copy link
Member Author

Choose a reason for hiding this comment

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

We might be able to get away with calling reset and release, letting the pool handle the recycling.

Copy link
Member Author

@gaaclarke gaaclarke Aug 21, 2023

Choose a reason for hiding this comment

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

I tried that and it didn't seem to be working as I expected. Printing out the CommandBuffers that are created didn't seem to recycle. Actually keeping the CommandBuffer around is a better way to assert that it is recycling at least.

Copy link
Contributor

Choose a reason for hiding this comment

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

command buffers themselves don't own any memory, the command pool is where the pooled memory is.

@chinmaygarde chinmaygarde changed the title [Impeller] added recycled command buffers [Impeller] Added recycled command buffers. Aug 21, 2023
@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 to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!).

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.

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

LGTM

@gaaclarke gaaclarke force-pushed the recycle-command-buffers-2 branch from 8d69b41 to 9418d73 Compare August 21, 2023 22:09
@gaaclarke gaaclarke merged commit 525df86 into flutter:main Aug 21, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 21, 2023
fluttermirroringbot pushed a commit to flutter/flutter that referenced this pull request Aug 22, 2023
gaaclarke added a commit to gaaclarke/engine that referenced this pull request Aug 30, 2023
Recycles command buffers instead of deleting them when they are done
being used.

@jonahwilliams profiled the Gallery on the Pixel 7 pro and saw that
sometimes `RenderPassVK::OnEncodeCommands` takes a long time in
flutter/flutter#132690. After adding adding
more tracing it was found that the culprit was deleting the
CommandBuffers on the raster thread. This PR removes the deletion of the
CommandBuffers and instead resets and recycles them.


![unnamed](https://github.com/flutter/engine/assets/30870216/2136dda0-6747-43a7-9a94-a0223c55b704)

> where GARBO2 is
> ```c++
> void CommandPoolVK::GarbageCollectBuffersIfAble() {
>   TRACE_EVENT0("impeller", "CommandPoolVK::GARBO2");
>    if (std::this_thread::get_id() != owner_id_) {    
>      return;  
>    }
>    buffers_to_collect_.clear();
> }
> ```

This approach matches the guidances from ["Vulkan Best Practice for
Mobile
Developers"](https://arm-software.github.io/vulkan_best_practice_for_mobile_developers/samples/performance/command_buffer_usage/command_buffer_usage_tutorial.html)
where it is preferable to recycle command buffers than delete them.
Also, the recommendation is that if you are not reusing command buffers
that you should periodically reset the pool, which we weren't doing.

issue: flutter/flutter#132690


## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I added new tests to check the change I am making or feature I am
adding, or Hixie said the PR is test-exempt. See [testing the engine]
for instructions on writing and running engine tests.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I signed the [CLA].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
@gaaclarke
Copy link
Member Author

gaaclarke commented Sep 22, 2023

This was a 10% drop in worst frame build time for new_gallery_impeller__transition_perf on SM-G973U1.

link

AVERAGE(62.63, 67.574, 59.244, 59.59, 67.145, 66.214, 55.63, 58.981, 56.337) / AVERAGE(53.647, 53.346, 59.414, 54.581, 55.753, 55.81, 55.447) = 0.9015253981

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants