[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed instances of unnecessary values #36221

Merged
merged 4 commits into from
Sep 26, 2022

Conversation

gaaclarke
Copy link
Member
@gaaclarke gaaclarke commented Sep 16, 2022

This removes superfluous copies, improves locality and takes advantages of moves when possible. It also adds a linter check too and removed superfluous moves of const variables.

Most of these changes are automated fixes from clang-tidy. I've reviewed the changes and fixed them where necessary. In aggregate they may cause a significant shift in performance of the engine. Many of the copy removals are in code that is hardly used, but others are high trafficked.

The big changes are:

  1. Eliminating copies of shared_ptr - this is expensive because it has a mutex
  2. Eliminating copies of sk_pr - does this have a mutex?
  3. Eliminating copies of closures - this can mask copies of captured variables
  4. Eliminating copies of vectors - I saw this a handful of places as well
  5. Eliminating RefPtr copies - this constructor is lightweight but we get locality benefits

There were too many instances to fix in one PR though. I tried to get them all but even this incomplete run is enough. I'll have to run clang-tidy with a few different variations of build files. I see there are a few impeller files that were missed for example that look important.

For testing I propose we look at skiaperf after this has landed to measure the impact. It should not hurt performance, but it also may not have a big impact on our performance tests.

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.

@flutter-dashboard flutter-dashboard bot added embedder Related to the embedder API platform-android labels Sep 16, 2022
@gaaclarke gaaclarke force-pushed the unnecessary-value branch 4 times, most recently from 885b04f to 00bf037 Compare September 16, 2022 22:16
@gaaclarke
Copy link
Member Author

So I double checked, this addresses all the issues I had in my current build target. Clang-tidy works based on your current build setup so to eliminate the other instances I'd have to run clang-tidy with those targets setup. I can do that in a different PR.

@gaaclarke gaaclarke changed the title Removed instances of unnecessary values (eliminates superfluous copies) Removed instances of unnecessary values Sep 16, 2022
Copy link
Member Author
@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

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

Here are a few instances that I think are worthwhile in particular.

@@ -62,7 +62,7 @@ class TextureRegistry {
TextureRegistry();

// Called from raster thread.
void RegisterTexture(std::shared_ptr<Texture> texture);
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 is potentially significant.

@@ -153,17 +153,17 @@ struct Command {
bool BindResource(ShaderStage stage,
const ShaderUniformSlot& slot,
const ShaderMetadata& metadata,
BufferView view);
Copy link
Member Author

Choose a reason for hiding this comment

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

These are potentially big (BufferView has a shared_ptr in it too).

Copy link
Member

Choose a reason for hiding this comment

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

Buffer view copies don't copy the buffer. They just have a pointer to the buffer.

@@ -61,7 +61,7 @@ class CommandBuffer {
///
/// @param[in] callback The completion callback.
///
[[nodiscard]] bool SubmitCommands(CompletionCallback callback);
Copy link
Member Author

Choose a reason for hiding this comment

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

potentially big

@@ -31,7 +31,8 @@ class Renderer {

bool IsValid() const;

bool Render(std::unique_ptr<Surface> surface, RenderCallback callback) const;
Copy link
Member Author

Choose a reason for hiding this comment

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

potentially big

@@ -31,7 +31,7 @@ class TextRun {
///
/// @param[in] font The font
///
TextRun(Font font);
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 sounds big. I'm not familiar with the code.

@@ -29,41 +29,42 @@ class SemanticsUpdateBuilder

~SemanticsUpdateBuilder() override;

void updateNode(int id,
Copy link
Member Author

Choose a reason for hiding this comment

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

seems significant too

@@ -32,9 +32,9 @@ struct ViewportMetrics {
double p_physical_system_gesture_inset_bottom,
double p_physical_system_gesture_inset_left,
double p_physical_touch_slop,
const std::vector<double> p_physical_display_features_bounds,
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 happen in an animation no? these vectors shouldn't be that big though.

@@ -256,7 +256,7 @@ class Rasterizer final : public SnapshotDelegate,
/// @param[in] discard_callback if specified and returns true, the layer tree
/// is discarded instead of being rendered
///
RasterStatus Draw(std::shared_ptr<LayerTreePipeline> pipeline,
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 looks big.

@@ -55,8 +55,8 @@ class SurfacePool {
std::shared_ptr<OverlayLayer> GetLayer(
GrDirectContext* gr_context,
const AndroidContext& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
Copy link
Member Author

Choose a reason for hiding this comment

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

seems impactful

@@ -18,8 +18,9 @@ class PlatformViewAndroidDelegate {
public:
explicit PlatformViewAndroidDelegate(
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
void UpdateSemantics(flutter::SemanticsNodeUpdates update,
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure what these classes are, but might be something here.

Copy link
Contributor
@dnfield dnfield left a comment

Choose a reason for hiding this comment

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

These LGTM, would appreciate review from Jason and Chinmay too

@@ -18,7 +18,7 @@ class InlinePassContext {
};

InlinePassContext(std::shared_ptr<Context> context,
RenderTarget render_target,
const RenderTarget& render_target,
Copy link
Member

Choose a reason for hiding this comment

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

This introduces a copy where one could have been elided before. That is, if the caller had moved in a render target. Now, the const reference necessitates a copy.

Copy link
Member Author

Choose a reason for hiding this comment

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

It doesn't necessitate one: https://godbolt.org/z/vEbY44YMP

Clang can just ignore the move.

uint32_t pass_texture_reads)
: context_(context),
: context_(std::move(context)),
Copy link
Member

Choose a reason for hiding this comment

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

This is is now a copy. The right fix here is to add the move but remove the const reference in the argument.

Copy link
Member Author
@gaaclarke gaaclarke Sep 19, 2022

Choose a reason for hiding this comment

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

For context? It went from 2 copies to 1 copy and one move. render_target is correct, that too went form 2 copies to one. When there is a custom copy constructor those shouldn't be able to be optimized away (edit, actually maybe it can, it does in the return case).

@@ -40,7 +40,7 @@ std::shared_ptr<DeviceBuffer> AllocatorGLES::OnCreateBuffer(
// |Allocator|
std::shared_ptr<Texture> AllocatorGLES::OnCreateTexture(
const TextureDescriptor& desc) {
return std::make_shared<TextureGLES>(reactor_, std::move(desc));
return std::make_shared<TextureGLES>(reactor_, desc);
Copy link
Member

Choose a reason for hiding this comment

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

Moving a const reference does nothing.

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, I also added a flag that removes moves of const.

@@ -21,7 +21,7 @@ class CommandBufferMTL final : public CommandBuffer {

id<MTLCommandBuffer> buffer_ = nullptr;

CommandBufferMTL(const std::weak_ptr<const Context> context,
CommandBufferMTL(const std::weak_ptr<const Context>& context,
Copy link
Member

Choose a reason for hiding this comment

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

Good catch.

@@ -9,7 +9,7 @@
namespace impeller {

TextureMTL::TextureMTL(TextureDescriptor p_desc, id<MTLTexture> texture)
: Texture(std::move(p_desc)), texture_(texture) {
: Texture(p_desc), texture_(texture) {
Copy link
Member

Choose a reason for hiding this comment

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

Good catch.

Copy link
Member
@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.

Copies of shared pointers don't acquire a mutex. They are just atomic bumps of control block reference counts. Also, at least some of the changes (I've highlighted a couple) make copy elision impossible even if the caller cooperated.

There are other changes in here that are useful though.

IMO, this patch is doing too much. Can we divvy it up into smaller chunks so its easier to review. Especially since this doens't seem to be a mechanical change thats always desirable to do as a matter of policy.

If its possible to gather numbers across all existing benchmarks after this change though, I love to see those before this lands. The speculative nature of this LSC makes me nervous.

@gaaclarke
Copy link
Member Author

Copies of shared pointers don't acquire a mutex. They are just atomic bumps of control block reference counts. Also, at least some of the changes (I've highlighted a couple) make copy elision impossible even if the caller cooperated.

Yea, you are right that they moved to std::atomic. I clearly haven't looked at shared_ptr source in a while.

With copy elision I think it's better to be explicit in the code than to rely on magic that may or may not happy in certain cases. We are using Microsoft's c++ compiler and standard library too on Windows no? So we have to consider their output as well which gets tricky.

There are other changes in here that are useful though.

IMO, this patch is doing too much. Can we divvy it up into smaller chunks so its easier to review. Especially since this doens't seem to be a mechanical change thats always desirable to do as a matter of policy.

If its possible to gather numbers across all existing benchmarks after this change though, I love to see those before this lands. The speculative nature of this LSC makes me nervous.

Sounds good, do you have a recommendation on what would be a good benchmark to see?

@gaaclarke
Copy link
Member Author

@chinmaygarde there is one more thing to consider too. This change is affecting the linter so that potentially guards us from performance errors in the future as well. So it isn't just about making what we have today faster, but also making sure we don't introduce an accidental value that has a negative effect on our performance.

@gaaclarke
Copy link
Member Author

It was decided in a PR review meeting that PR's that make the codebase more consistent and cleaner do not need to prove performance gains.

@gaaclarke
Copy link
Member Author

@chinmaygarde I merged master with the following method. Can you please give this a quick look before it atrophies given our decision from the PR review meeting decision.

How to update:

  1. Merge upstream/main
  2. Checkout current for all merge conflicts
  3. Build the target and fix any build problems
  4. Run clang-tidy fix again

@@ -17,7 +17,7 @@ LazyGlyphAtlas::~LazyGlyphAtlas() = default;
void LazyGlyphAtlas::AddTextFrame(const TextFrame& frame) {
FML_DCHECK(atlas_map_.empty());
has_color_ |= frame.HasColor();
frames_.emplace_back(std::move(frame));
frames_.emplace_back(frame);
Copy link
Member Author

Choose a reason for hiding this comment

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

I was a bit surprised this works, but it does, fun c++.

@gaaclarke
Copy link
Member Author

The last failure was human error. Any clang-tidy fix that compiles but fails at execution time would be grounds to abandon this change, but that wasn't the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App embedder Related to the embedder API platform-android
Projects
None yet
3 participants