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

Add flushUIThreadTasks service RPC #3898

Merged
merged 3 commits into from
Jul 19, 2017
Merged

Add flushUIThreadTasks service RPC #3898

merged 3 commits into from
Jul 19, 2017

Conversation

B3rn475
Copy link
Contributor

@B3rn475 B3rn475 commented Jul 18, 2017

In #3833 the _flutter.listViews RPC moved from thread based to lock based synchronization.
The thread based synchronization side effect was used by flutter benchmarks in https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/vmservice.dart#L1223 and
https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/run_hot.dart#L156 to ensure the completeness of the restart/reload and so correct timing.

A new RPC _flutter.flushUIThreadTasks is introduced to allow the flutter benchmarks to reintroduce thread based synchronization.

Related flutter/flutter#11241

In #3833 the _flutter.listViews
RPC moved from thread based to lock based synchronization.
The thread based synchronization side effect was used by flutter
benchmarks in
https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/vmservice.dart#L1223
and
https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/run_hot.dart#L156
to ensure the completeness of the restart/reload and so correct
timing.

A new RPC _flutter.waitUIThreadIdle is introduced to allow the
flutter benchmarks to reintroduce thread based synchronization.

Related flutter/flutter#11241
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
Copy link
Contributor

Choose a reason for hiding this comment

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

Indentation seems off

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

@@ -314,4 +316,29 @@ void PlatformViewServiceProtocol::ScreenshotGpuTask(SkBitmap* bitmap) {
canvas->flush();
}

const char* PlatformViewServiceProtocol::kWaitUIThreadIdleExtensionName =
"_flutter.waitUIThreadIdle";
Copy link
Contributor

Choose a reason for hiding this comment

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

Strictly speaking this is not waiting for the UI thread to idle it is more wait for UI thread to finish processing the first event, I don't have a better name for it though.

Copy link
Contributor

Choose a reason for hiding this comment

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

How about FlushUIThreadTasks?

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 is not actually flushing all the tasks, but just the first one.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure? The implementation calls blink::Threads::UI()->PostTask, which will queue up a task. Given that the message queue is FIFO, all tasks that were scheduled prior to this task will execute first. No?

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 misunderstood the meaning of Tasks, you are right. It will wait for all the previous tasks to be flushed.

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

@yjbanov yjbanov requested a review from jason-simmons July 18, 2017 23:02
@yjbanov
Copy link
Contributor

yjbanov commented Jul 18, 2017

Added @jason-simmons to reviewer list for C++/engine readability.


// This API should not be invoked by production code.
// It can potentially starve the service isolate if the main isolate pauses
// at a breakpoint or is in an infinite loop.
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth mentioning that this method must be invoked from the VM service thread and blocks it until UI thread tasks are processed.

Copy link
Contributor Author

@B3rn475 B3rn475 Jul 18, 2017

Choose a reason for hiding this comment

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

Should we add this description even to the other services? some of them are blocking too.

Copy link
Contributor

Choose a reason for hiding this comment

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

That would be great. We have comments like that in shell.h.

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

@@ -314,4 +316,29 @@ void PlatformViewServiceProtocol::ScreenshotGpuTask(SkBitmap* bitmap) {
canvas->flush();
}

const char* PlatformViewServiceProtocol::kWaitUIThreadIdleExtensionName =
"_flutter.waitUIThreadIdle";
Copy link
Contributor

Choose a reason for hiding this comment

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

How about FlushUIThreadTasks?

@@ -43,6 +43,17 @@ class PlatformViewServiceProtocol {
void* user_data,
const char** json_object);
static void ScreenshotGpuTask(SkBitmap* bitmap);

// This API should not be invoked by production code.
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto re calling from VM isolate thread

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

@Hixie
Copy link
Contributor

Hixie commented Jul 19, 2017

So if I understand correctly, the claim here is that hot_mode_dev_cycle__benchmark hotRestartMillisecondsToFrame used to count the entire cycle of "wait for UI thread to be stable, tell app to restart, then wait for app to be done", and now it only counts "tell app to restart, then wait for app to be done"?

Similarly, is the claim that hot_mode_dev_cycle__benchmark hotReloadMillisecondsToFrame used to not count the time waiting for the app to be stable before triggering the hot reload, but now that it does include that time, the reload takes two SECONDS more?

I find it surprising that both of these benchmarks imply that the app is locked for two seconds every time, reliably. There's very little noise in how much difference the benchmarks are seeing.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jul 19, 2017

@Hixie
The claim is that hot_mode_dev_cycle__benchmark hotRestartMillisecondsToFrame used to count:

  • tell app to restart
  • wait for the Isolate to start
  • wait for the app to be done / wait for UI thread to be empty (side effect of synchronously listing the views)

while hot_mode_dev_cycle__benchmark hotReloadMillisecondsToFrame used to count:

  • hot reload
  • reassemble
  • schedule frame

Now instead hot_mode_dev_cycle__benchmark hotRestartMillisecondsToFrame counts:

  • tell app to restart
  • wait for the Isolate to start
  • (no "wait for UI thread to be empty" side effect of asynchronously listing the views)

while hot_mode_dev_cycle__benchmark hotReloadMillisecondsToFrame counts:

  • wait for the app to be done / wait for UI thread to be empty (side effect of triggering hot reload)
  • hot reload
  • reassemble
  • schedule frame

We are actually counting a part of hotRestartMillisecondsToFrame inside hotReloadMillisecondsToFrame instead.

@Hixie
Copy link
Contributor

Hixie commented Jul 19, 2017

That implies that it takes ~2500 milliseconds for an app to start ("wait for the app to be done / wait for UI thread to be empty"), and ~2000ms for an idle app to be ready to be hot reloaded, both of which seems exceedingly high.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jul 19, 2017

On my device we can see this:

[        ] Benchmarking hot restart
[        ] Performing full restart...
[   +1 ms] Refreshing active FlutterViews before restarting.
[ +262 ms] Syncing files to device A0001...
[        ] DevFS: Starting sync from LocalDirectory: '.../flutter/examples/flutter_gallery'
[        ] Scanning project files
[   +3 ms] Scanning package files
[  +24 ms] Scanning asset files
[   +1 ms] Scanning for deleted files
[   +2 ms] DevFS: Sync finished
[        ] Synced 0.0MB.
[+1543 ms] Isolate is runnable.
[+2781 ms] Restart performed in 4,561ms.
[   +2 ms] Restarted app in 4,623ms.

It takes:

  • ~250 ms to synchronize DevFS (even if nothing is changed)
  • ~1300 ms to get to the IsolateRunnable event
  • ~1200 ms for the UI thread to Flush all the tasks (AFAIK render the application)

@B3rn475 B3rn475 changed the title Add waitUIThreadIdle service RPC Add flushUIThreadTasks service RPC Jul 19, 2017
@B3rn475 B3rn475 merged commit 53c9a70 into flutter:master Jul 19, 2017
@B3rn475 B3rn475 deleted the benchmark branch July 19, 2017 22:48
B3rn475 added a commit to flutter/flutter that referenced this pull request Jul 19, 2017
Changes introduced in
flutter/engine@8ba522e
has removed from the `_flutter.listViews` the thread synchronization
side effect used during benchmarks.

The thread synchronization is restored via the new
`_flutter.flushUIThreadTasks` RPC.

Fixes #11241

Related flutter/engine#3898
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants