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

Hashing closures is slow #47873

Closed
dnfield opened this issue Dec 7, 2021 · 12 comments
Closed

Hashing closures is slow #47873

dnfield opened this issue Dec 7, 2021 · 12 comments
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. customer-flutter

Comments

@dnfield
Copy link
Contributor

dnfield commented Dec 7, 2021

The framework has a relatively hot path on build when using text widgets that calls this:

https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/painting/binding.dart#L164

With a tearoff closure from a mixin. This ends up computing the hash code of the closure, which goes through this path in the VM, which is bubbling up in profiling as taking significant time:

sdk/runtime/vm/object.cc

Lines 9525 to 9532 in 7359264

intptr_t Function::ComputeClosureHash() const {
ASSERT(IsClosureFunction());
const Class& cls = Class::Handle(Owner());
uintptr_t result = String::Handle(name()).Hash();
result += String::Handle(InternalSignature()).Hash();
result += String::Handle(cls.Name()).Hash();
return result;
}

@rmacnak-google says this is slow and could be implemented to be a lot faster. At the very least, it seems strange to me that its getting strings, computing their hash codes, and then adding them.

/cc @a-siva @goderbauer

@dnfield dnfield added area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. customer-flutter labels Dec 7, 2021
@dnfield
Copy link
Contributor Author

dnfield commented Dec 7, 2021

FWIW: The use case here is going to be changed in the framework code to use a more optimized ChangeNotifier implementation that is backed by a List rather than Set. However, I wonder if part of the optimization path there was working around this issue with hashing.

@rmacnak-google
Copy link
Contributor

Also the general case identity hash could be rewritten to not need a runtime call.

@mraleph
Copy link
Member

mraleph commented Dec 7, 2021

The suspect there is InternalSignature - the rest are just combining precomputed hashes and should be relatively quick. Though it is indeed unfortunate that you need to go to runtime at all to compute this hash the first time for each newly created closure.

/cc @alexmarkov who looked at closure hashes before in https://codereview.chromium.org/2983823002/

@dnfield
Copy link
Contributor Author

dnfield commented Dec 7, 2021

Yes, InternalSignature is what bubbles up in the trace (and its call to BaseTextBuffer::addString).

@dnfield
Copy link
Contributor Author

dnfield commented Dec 13, 2021

This ended up being not as trivial to fix in the framework, but also not showing a huge win in real application workloads. It'd still be good to have a fix for it, since I suspect Flutter applications will end up on this path at times.

copybara-service bot pushed a commit that referenced this issue Dec 13, 2021
Generating identity hashes from the runtime no longer calls into Dart. On 32-bit systems, generating identity hashes from Dart now does only one runtime transition.

TEST=ci
Bug: #47873
Change-Id: Ib21156cb05706f81744eb4e5ccb644f40aa84c96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222326
Reviewed-by: Alexander Markov <alexmarkov@google.com>
@mraleph
Copy link
Member

mraleph commented Dec 14, 2021

I think @rmacnak-google has fixed this in ecdf148 .

@mraleph mraleph closed this as completed Dec 14, 2021
@mraleph
Copy link
Member

mraleph commented Dec 14, 2021

(There is still one runtime crossing for each new closure as I understand it - so it could probably be improved further, but at least we don't format signatures as strings anymore).

@dnfield
Copy link
Contributor Author

dnfield commented Dec 14, 2021

This rolled into flutter/engine in flutter/engine#30327

As of this writing, it has not rolled into framework. However local profiling that drew my attention to this shows marked improvement - it's a little hard for me to precisely quantify given the tooling, but I'm not even really seeing this in CPU profiling where Iw as seeing it before.

@a-siva
Copy link
Contributor

a-siva commented Feb 25, 2022

@dnfield Can this issue be closed ?

@dnfield
Copy link
Contributor Author

dnfield commented Feb 25, 2022

It is closed and can stay closed :). Did you mean to post this on a different issue?

@a-siva
Copy link
Contributor

a-siva commented Feb 25, 2022

You had a comment that it hadn't rolled into the framework and I was wondering if some issues were found when rolling into the framework. I guess it can remain closed.

@dnfield
Copy link
Contributor Author

dnfield commented Feb 25, 2022

Ahhh haha I tested it manually before it rolled in is all. Sorry for confusion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. customer-flutter
Projects
None yet
Development

No branches or pull requests

4 participants