[engine] support combined UI/Platform thread for iOS/Android.
Experimentally support merging UI and platform thread on Android/iOS. This works by changing the shell holder to set the UI thread to the platform thread. Several shell APIs that post messages from the platform to ui thread were changed to use RunNowOrPostTask to immediately call the UI task if the threads are the same.
Experimentally, this seems to work reasonably well if there are no platform views. On Android with TLHC it works fine either way, while iOS currently takes a big performance hit.
This can be opted into via a Plist:
<key>FLTEnableMergedPlatformUIThread</key>
<true/>
Or via AndroidManifest.xml:
<meta-data
android:name="io.flutter.embedding.android.EnableMergedPlatformUIThread"
android:value="true" />
https://github.com/flutter/flutter/issues/150525
The tester shells are already running in a combined thead mode (unless run with --force-multithreading).
It is easy to go merge the threads but there is no going back because of plugins.
Adding an experimental option that we don't advertise is not a one way door. Anyone that ships code that depends on this behavior can be broken
I love this! I'll try to get this working on macOS with the resize synchronizer, but I'm not sure how much time I'm going to have this week (FlutterCon).
Btw. the io.flutter.1.ui thread still gets created, just sitting there empty.
I have a very fragile and buggy but working macOS proof of concept working. The idea is to short-circuit macOS vsync waiter during resizing to fire immediately, and then to modify the vsync waiter machinery in the engine so that if the vsync callback is called from UI thread and frame_start_time is in past, it will trigger the frame immediately instead.
Btw. the io.flutter.1.ui thread still gets created, just sitting there empty.
Should be fixed now.
I've a WIP PR for macos here. Some remaining open questions there, mostly regarding the microtask queue.
@chinmaygarde do you intend to review this patch?
I simply can't agree that an experimental flag presents an opportunity for ecosystem breakage. I agree that we should good answers for the question of performance before we make this the default behavior, but opting in for testing and experimentation is well within the realm of changes like platform isolates, wide gamut, impeller, et cetera.
If the plugin assumes merged UI and platform thread, it would mean that the plugin imposes the flag on the end user, which I don't really like. For example with super_drag_and_drop and super_clipboard, I make quite a few assumptions about threading (I routinely need to pause platform thread to while getting answer from UI thread). I plan to support merged threads as soon as it lands on all platforms, but as an addition to the default threading model, and not exclusively.
I think we need to communicate this clearly that if plugins make threading assumptions, they need to support both models for the time being, and never force the flag on end user.
I am not sure you can force plugin authors to support both models. Exposing to plugins which model is being used then asking nicely might be your only option. If you let plugin authors detect the threading model and let the apps set the threading model then plugin authors can choose how to handle the difference. Plugins that dont care can Ignore the change, some will support both, some can throw exceptions or can use the thread model to enable or disable a subset of features.
To be clear, this flag is for our own experimentation.
There is absoltely no plan to make this a configurable option for developers. Either we find a means to merge the platform and ui threads, in general, and make that the only default behavior, or we don't.
I'm not currently aware of any circumstances where moving from un merged to merged thread model will break any plugins, but this is something that I hope to discover this quarter. (I could certainly see the opposite breaking plugins, but that won't be a configurable option)
This will absolutely cause super_drag_and_drop to deadlock, since it needs to respond to synchronous platform callbacks and it does it by carefully blocking the platform thread until it has response from UI thread. But I also think this is a very uncommon scenario.
Assuming we had a solution to the other thread merging problems, I'd like us to handle that with some like "Starting from (Future) version 3.XX, threads will be merged, if you do X/Y/Z instead do A/B/C" instead of letting folks opt in or out.