Skip to content

Conversation

@jmagman
Copy link
Member

@jmagman jmagman commented Jul 22, 2020

Description

When a command is run with --device all relevant platform device discoverers gather all devices, which are then checked if the identifier or name exactly matches the specified device ID, then if they match the prefix of the specified device ID. Some device discoverers with hard-coded return very quickly (flutter-tester, chrome, macos, linux), and others that shell out to underlying tools (Android, iOS, Fuschia) take much longer.

Instead of gathering all devices first, process them as they are discovered, and return quickly if an exact match is found.

Here are discovery times for exact matches on top of tree vs this PR (note these times include the overhead of calling a command I hacked the timing into, it's not how long this function took):

master PR
flutter-tester 1.49s 0.58s
chrome 1.51s 0.61s
macos 1.48s 0.59s
iOS device identifier 1.48s 1.27s

Before this change, all times were about the same, because it waited for all platform discoveries to be complete before matching. After this change, the time takes as long as the relevant discoverer can return.

Related Issues

Fixes #61466
Fixes #44898
Relevant for #15072 increasing discovery times when an exact networking iOS ID is specified without regressing other platforms.

Tests

getDeviceById exact matcher uses new LongPollingDeviceDiscovery that never finishes polling. Exact matches are still returned quickly. This test runs forever on master.

Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I signed the [CLA].
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

  • No, no existing tests failed, so this is not a breaking change.
  • Yes, this is a breaking change. If not, delete the remainder of this section.

@jmagman jmagman requested review from DanTup and jonahwilliams July 22, 2020 22:06
@jmagman jmagman self-assigned this Jul 22, 2020
@fluttergithubbot
Copy link
Contributor

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.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@fluttergithubbot fluttergithubbot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jul 22, 2020
@jmagman jmagman force-pushed the fast-device-discover branch from 75929f7 to 63b054c Compare July 22, 2020 22:07
@jonahwilliams
Copy link
Contributor

Very nice! I think you could construct a new test case that will now pass that would have failed. Consider two device discoverers, one returns instantly and one never returns.

@jmagman
Copy link
Member Author

jmagman commented Jul 22, 2020

Very nice! I think you could construct a new test case that will now pass that would have failed. Consider two device discoverers, one returns instantly and one never returns.

Done.

];

// Wait for an exact match, or for all discoverers to return results.
await Future.any<dynamic>(<Future<dynamic>>[
Copy link
Contributor

@jonahwilliams jonahwilliams Jul 22, 2020

Choose a reason for hiding this comment

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

The edge case Zach mentioned is a bit more obvious when streams aren't used. In this case, after Future.any completes the first future, the second future may still complete w/error. That would cause an unhandled exception to be thrown into the zone.

You could simulate this a similar 2 discoverer setup where one throws an error after another turn.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, added test for this as well.

return null;
}, onError: (dynamic error, StackTrace stackTrace) {
// Return matches from other discoverers even if one fails.
globals.printTrace('Ignored error discovering $deviceId: $error');
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is almost the behavior we want, thought it's not quite the same as before. Previously if a discoverer crashed, we would surface that and go straight to crash logging. Especially if we don't match an exact device, knowing that some discovery has crashed is probably important, but I don't think that it should stop users from running on unrelated devices.

Unsure what the right solution is.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe if there is any error, and the target device isn't found, print an error directing the user to flutter devices or flutter doctor --verbose.

Copy link
Member Author

@jmagman jmagman Jul 23, 2020

Choose a reason for hiding this comment

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

I was happy with the old crashing behavior so we'd at least see it, but I'm still missing something related to why it matters if it's unhandled and thrown into the zone.

That would cause an unhandled exception to be thrown into the zone.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was actually wrong about this. Future.any will explicitly discard errors thrown by future's other than the first. I think what you have here is good

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

@jmagman jmagman merged commit f9499f4 into flutter:master Jul 24, 2020
@jmagman jmagman deleted the fast-device-discover branch July 24, 2020 23:15
Pragya007 pushed a commit to Pragya007/flutter that referenced this pull request Aug 11, 2020
mingwandroid pushed a commit to mingwandroid/flutter that referenced this pull request Sep 6, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

5 participants