Skip to content

Cache the results of getVersion and getIsolate #3309

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

Merged
merged 13 commits into from
Sep 3, 2021
67 changes: 39 additions & 28 deletions packages/devtools_app/lib/src/service_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ const defaultRefreshRate = 60.0;
// instead of Streams.
class ServiceConnectionManager {
ServiceConnectionManager() {
_serviceExtensionManager =
ServiceExtensionManager(isolateManager.mainIsolate);
_serviceExtensionManager = ServiceExtensionManager(isolateManager);
}

final StreamController<VmServiceWrapper> _connectionAvailableController =
Expand Down Expand Up @@ -763,13 +762,13 @@ class IsolateManager extends Disposer {

/// Manager that handles tracking the service extension for the main isolate.
class ServiceExtensionManager extends Disposer {
ServiceExtensionManager(this._mainIsolate);
ServiceExtensionManager(this._isolateManager);

VmServiceWrapper _service;

bool _checkForFirstFrameStarted = false;

final ValueListenable<IsolateRef> _mainIsolate;
final IsolateManager _isolateManager;

Future<void> get firstFrameReceived => _firstFrameReceived.future;
Completer<void> _firstFrameReceived = Completer();
Expand Down Expand Up @@ -903,39 +902,46 @@ class ServiceExtensionManager extends Disposer {
}

Future<void> _onMainIsolateChanged() async {
if (_mainIsolate.value == null) {
if (_isolateManager.mainIsolate.value == null) {
_mainIsolateClosed();
return;
}
_checkForFirstFrameStarted = false;

final isolateRef = _mainIsolate.value;
final Isolate isolate = await _service.getIsolate(isolateRef.id);
if (isolateRef != _mainIsolate.value) {
final isolateRef = _isolateManager.mainIsolate.value;
final Isolate isolate = await _isolateManager.getIsolateCached(isolateRef);

await _registerMainIsolate(isolate, isolateRef);
}

Future<void> _registerMainIsolate(
Isolate mainIsolate, IsolateRef expectedMainIsolateRef) async {
if (expectedMainIsolateRef != _isolateManager.mainIsolate.value) {
// Isolate has changed again.
return;
}
if (isolate.extensionRPCs != null) {

if (mainIsolate.extensionRPCs != null) {
if (await connectedApp.isFlutterApp) {
if (isolateRef != _mainIsolate.value) {
if (expectedMainIsolateRef != _isolateManager.mainIsolate.value) {
// Isolate has changed again.
return;
}
await Future.wait([
for (String extension in isolate.extensionRPCs)
for (String extension in mainIsolate.extensionRPCs)
_maybeAddServiceExtension(extension)
]);
} else {
await Future.wait([
for (String extension in isolate.extensionRPCs)
for (String extension in mainIsolate.extensionRPCs)
_addServiceExtension(extension)
]);
}
}
}

Future<void> _maybeCheckForFirstFlutterFrame() async {
final _lastMainIsolate = _mainIsolate.value;
final _lastMainIsolate = _isolateManager.mainIsolate.value;
if (_checkForFirstFrameStarted ||
_firstFrameEventReceived ||
_lastMainIsolate == null) return;
Expand All @@ -948,7 +954,7 @@ class ServiceExtensionManager extends Disposer {
extensions.didSendFirstFrameEvent,
isolateId: _lastMainIsolate.id,
);
if (_lastMainIsolate != _mainIsolate.value) {
if (_lastMainIsolate != _isolateManager.mainIsolate.value) {
// The active isolate has changed since we started querying the first
// frame.
return;
Expand Down Expand Up @@ -995,7 +1001,7 @@ class ServiceExtensionManager extends Disposer {
}

Future<void> _restoreExtensionFromDevice(String name) async {
final isolateRef = _mainIsolate.value;
final isolateRef = _isolateManager.mainIsolate.value;
if (isolateRef == null) return;

if (!extensions.serviceExtensionsAllowlist.containsKey(name)) {
Expand All @@ -1006,14 +1012,14 @@ class ServiceExtensionManager extends Disposer {

Future<void> restore() async {
// The restore request is obsolete if the isolate has changed.
if (isolateRef != _mainIsolate.value) return;
if (isolateRef != _isolateManager.mainIsolate.value) return;
try {
final response = await _service.callServiceExtension(
name,
isolateId: isolateRef.id,
);

if (isolateRef != _mainIsolate.value) return;
if (isolateRef != _isolateManager.mainIsolate.value) return;

switch (expectedValueType) {
case bool:
Expand Down Expand Up @@ -1044,10 +1050,10 @@ class ServiceExtensionManager extends Disposer {
}
}

if (isolateRef != _mainIsolate.value) return;
if (isolateRef != _isolateManager.mainIsolate.value) return;

final Isolate isolate = await _service.getIsolate(isolateRef.id);
if (isolateRef != _mainIsolate.value) return;
final Isolate isolate = await _isolateManager.getIsolateCached(isolateRef);
if (isolateRef != _isolateManager.mainIsolate.value) return;

// Do not try to restore Dart IO extensions for a paused isolate.
if (extensions.isDartIoExtension(name) &&
Expand Down Expand Up @@ -1075,9 +1081,9 @@ class ServiceExtensionManager extends Disposer {
return;
}

final mainIsolate = _mainIsolate.value;
final mainIsolate = _isolateManager.mainIsolate.value;
Future<void> callExtension() async {
if (_mainIsolate.value != mainIsolate) return;
if (_isolateManager.mainIsolate.value != mainIsolate) return;

assert(value != null);
if (value is bool) {
Expand Down Expand Up @@ -1131,8 +1137,8 @@ class ServiceExtensionManager extends Disposer {
}

if (mainIsolate == null) return;
final Isolate isolate = await _service.getIsolate(mainIsolate.id);
if (_mainIsolate.value != mainIsolate) return;
final Isolate isolate = await _isolateManager.getIsolateCached(mainIsolate);
if (_isolateManager.mainIsolate.value != mainIsolate) return;

// Do not try to call Dart IO extensions for a paused isolate.
if (extensions.isDartIoExtension(name) &&
Expand Down Expand Up @@ -1247,7 +1253,8 @@ class ServiceExtensionManager extends Disposer {
);
}

void vmServiceOpened(VmServiceWrapper service, ConnectedApp connectedApp) {
void vmServiceOpened(
VmServiceWrapper service, ConnectedApp connectedApp) async {
_checkForFirstFrameStarted = false;
cancel();
_connectedApp = connectedApp;
Expand All @@ -1258,11 +1265,15 @@ class ServiceExtensionManager extends Disposer {
hasServiceExtension(extensions.didSendFirstFrameEvent),
_maybeCheckForFirstFlutterFrame,
);
addAutoDisposeListener(_mainIsolate, _onMainIsolateChanged);
addAutoDisposeListener(_isolateManager.mainIsolate, _onMainIsolateChanged);
autoDispose(service.onDebugEvent.listen(_handleDebugEvent));
autoDispose(service.onIsolateEvent.listen(_handleIsolateEvent));
if (_mainIsolate.value != null) {
_onMainIsolateChanged();
final mainIsolateRef = _isolateManager.mainIsolate.value;
if (mainIsolateRef != null) {
_checkForFirstFrameStarted = false;
final mainIsolate =
await _isolateManager.getIsolateCached(mainIsolateRef);
await _registerMainIsolate(mainIsolate, mainIsolateRef);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions packages/devtools_app/lib/src/vm_service_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,10 @@ class VmServiceWrapper implements VmService {
}

@override
Future<Version> getVersion() =>
trackFuture('getVersion', _vmService.getVersion());
Future<Version> getVersion() async {
return _protocolVersion ??=
await trackFuture('getVersion', _vmService.getVersion());
}

Future<Version> getDartIOVersion(String isolateId) =>
trackFuture('_getDartIOVersion', _vmService.getDartIOVersion(isolateId));
Expand Down