From e522c7ee5082baf5b03285e06f3ada98a1596df6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 12:08:57 -0700 Subject: [PATCH 01/97] - --- packages/devtools_app/lib/src/app.dart | 3 ++- .../lib/src/example/conditional_screen.dart | 2 +- .../lib/src/shared/feature_flags.dart | 6 ++++- .../lib/src/shared/offline_data.dart | 6 ++--- .../devtools_app/lib/src/shared/screen.dart | 25 +++++++++++-------- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index f8d5232c0d2..249d2b88666 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -373,7 +373,8 @@ class DevToolsAppState extends State with AutoDisposeMixin { return widget.originalScreens .where( (s) => - s.providesController && (offline ? s.screen.worksOffline : true), + s.providesController && + (offline ? s.screen.worksWithOfflineData : true), ) .map((s) => s.controllerProvider(routerDelegate)) .toList(); diff --git a/packages/devtools_app/lib/src/example/conditional_screen.dart b/packages/devtools_app/lib/src/example/conditional_screen.dart index 0de55e4b128..d5171791346 100644 --- a/packages/devtools_app/lib/src/example/conditional_screen.dart +++ b/packages/devtools_app/lib/src/example/conditional_screen.dart @@ -24,7 +24,7 @@ class ExampleConditionalScreen extends Screen { requiresLibrary: 'package:flutter/', title: 'Example', icon: Icons.palette, - worksOffline: true, + worksWithOfflineData: true, ); static const id = 'example'; diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index f268637fb1f..89953766193 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -35,6 +35,9 @@ void setEnableExperiments() { @visibleForTesting bool get enableBeta => enableExperiments || !isExternalBuild; +const bool kMemoryAnalysisExperiment = + bool.fromEnvironment('memory_analysis_experiment'); + // It is ok to have enum-like static only classes. // ignore: avoid_classes_with_only_static_members /// Flags to hide features under construction. @@ -56,7 +59,8 @@ abstract class FeatureFlags { /// Flag to enable analysis of snapshots in disconnected mode. /// /// https://github.com/flutter/devtools/issues/5606 - static bool memoryAnalysis = enableExperiments; + static bool memoryAnalysis = + kMemoryAnalysisExperiment; // requires special handling because it needs to be const /// Flag to enable the deep link validation tooling in DevTools, both for the /// DevTools screen and the standalone tool for IDE embedding. diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index 7a6eac13b87..8d0fa5da8a4 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -66,7 +66,7 @@ class OfflineDataController { /// Mixin that provides offline support for a DevTools screen controller. /// /// The [Screen] that is associated with this controller must have -/// [Screen.worksOffline] set to true in order to enable offline support for the +/// [Screen.worksWithOfflineData] set to true in order to enable offline support for the /// screen. /// /// Check [OfflineDataController.showingOfflineData] in controller constructor. @@ -108,13 +108,13 @@ class OfflineDataController { /// /// ... /// -/// Then in the DevTools [ScreenMetaData] enum, set 'worksOffline' to true. +/// Then in the DevTools [ScreenMetaData] enum, set 'worksWithOfflineData' to true. /// /// enum ScreenMetaData { /// ... /// myScreen( /// ... -/// worksOffline: true, +/// worksWithOfflineData: true, /// ), /// } mixin OfflineScreenControllerMixin on AutoDisposeControllerMixin { diff --git a/packages/devtools_app/lib/src/shared/screen.dart b/packages/devtools_app/lib/src/shared/screen.dart index c43063b6fc5..60cb60839c0 100644 --- a/packages/devtools_app/lib/src/shared/screen.dart +++ b/packages/devtools_app/lib/src/shared/screen.dart @@ -11,6 +11,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; +import 'feature_flags.dart'; import 'globals.dart'; import 'primitives/listenable.dart'; import 'ui/icons.dart'; @@ -36,7 +37,7 @@ enum ScreenMetaData { 'performance', title: 'Performance', icon: Octicons.pulse, - worksOffline: true, + worksWithOfflineData: true, requiresConnection: false, tutorialVideoTimestamp: '?t=261', ), @@ -45,7 +46,7 @@ enum ScreenMetaData { title: 'CPU Profiler', icon: Octicons.dashboard, requiresDartVm: true, - worksOffline: true, + worksWithOfflineData: true, requiresConnection: false, tutorialVideoTimestamp: '?t=340', ), @@ -55,6 +56,8 @@ enum ScreenMetaData { icon: Octicons.package, requiresDartVm: true, tutorialVideoTimestamp: '?t=420', + // ignore: avoid_redundant_argument_values, false positive + worksWithOfflineData: kMemoryAnalysisExperiment, ), debugger( 'debugger', @@ -115,7 +118,7 @@ enum ScreenMetaData { this.requiresFlutter = false, this.requiresDebugBuild = false, this.requiresVmDeveloperMode = false, - this.worksOffline = false, + this.worksWithOfflineData = false, this.requiresLibrary, this.tutorialVideoTimestamp, }); @@ -128,7 +131,7 @@ enum ScreenMetaData { final bool requiresFlutter; final bool requiresDebugBuild; final bool requiresVmDeveloperMode; - final bool worksOffline; + final bool worksWithOfflineData; final String? requiresLibrary; /// The timestamp for the chapter of "Dive in to DevTools" YouTube video that @@ -175,7 +178,7 @@ abstract class Screen { this.requiresFlutter = false, this.requiresDebugBuild = false, this.requiresVmDeveloperMode = false, - this.worksOffline = false, + this.worksWithOfflineData = false, this.showFloatingDebuggerControls = true, }) : assert((title == null) || (titleGenerator == null)); @@ -187,7 +190,7 @@ abstract class Screen { bool requiresFlutter = false, bool requiresDebugBuild = false, bool requiresVmDeveloperMode = false, - bool worksOffline = false, + bool worksWithOfflineData = false, bool Function(FlutterVersion? currentVersion)? shouldShowForFlutterVersion, bool showFloatingDebuggerControls = true, String? title, @@ -202,7 +205,7 @@ abstract class Screen { requiresFlutter: requiresFlutter, requiresDebugBuild: requiresDebugBuild, requiresVmDeveloperMode: requiresVmDeveloperMode, - worksOffline: worksOffline, + worksWithOfflineData: worksWithOfflineData, showFloatingDebuggerControls: showFloatingDebuggerControls, title: title, titleGenerator: titleGenerator, @@ -224,7 +227,7 @@ abstract class Screen { requiresFlutter: metadata.requiresFlutter, requiresDebugBuild: metadata.requiresDebugBuild, requiresVmDeveloperMode: metadata.requiresVmDeveloperMode, - worksOffline: metadata.worksOffline, + worksWithOfflineData: metadata.worksWithOfflineData, shouldShowForFlutterVersion: shouldShowForFlutterVersion, showFloatingDebuggerControls: showFloatingDebuggerControls, title: titleGenerator == null ? metadata.title : null, @@ -292,7 +295,7 @@ abstract class Screen { final bool requiresVmDeveloperMode; /// Whether this screen works offline and should show in offline mode even if conditions are not met. - final bool worksOffline; + final bool worksWithOfflineData; /// Whether this screen should display the isolate selector in the status /// line. @@ -439,8 +442,8 @@ abstract class Screen { bool shouldShowScreen(Screen screen) { _log.finest('shouldShowScreen: ${screen.screenId}'); if (offlineDataController.showingOfflineData.value) { - _log.finest('for offline mode: returning ${screen.worksOffline}'); - return screen.worksOffline; + _log.finest('for offline mode: returning ${screen.worksWithOfflineData}'); + return screen.worksWithOfflineData; } final serviceReady = serviceConnection.serviceManager.isServiceAvailable && From ebded8c0393a21bff01de37ed06a33ea56c12432 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 12:22:20 -0700 Subject: [PATCH 02/97] Update launch.json --- packages/.vscode/launch.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/.vscode/launch.json b/packages/.vscode/launch.json index 7f009c315ab..95a8c280e63 100644 --- a/packages/.vscode/launch.json +++ b/packages/.vscode/launch.json @@ -22,7 +22,9 @@ "type": "dart", "program": "devtools_app/lib/main.dart", "args": [ - "--dart-define=enable_experiments=true" + "--dart-define", + "memory_analysis_experiment=true", + "enable_experiments=true", ], }, { From 3c87709b0ef9a4fcb46f79ebf3502e8008557618 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 12:28:58 -0700 Subject: [PATCH 03/97] - --- packages/.vscode/launch.json | 2 +- packages/devtools_app/lib/src/shared/feature_flags.dart | 8 ++++---- packages/devtools_app/lib/src/shared/screen.dart | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/.vscode/launch.json b/packages/.vscode/launch.json index 95a8c280e63..b9b6201c12d 100644 --- a/packages/.vscode/launch.json +++ b/packages/.vscode/launch.json @@ -23,7 +23,7 @@ "program": "devtools_app/lib/main.dart", "args": [ "--dart-define", - "memory_analysis_experiment=true", + "memory_offline_experiment=true", "enable_experiments=true", ], }, diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index bc6f39c64b2..4a74523641e 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -35,8 +35,8 @@ void setEnableExperiments() { @visibleForTesting bool get enableBeta => enableExperiments || !isExternalBuild; -const bool kMemoryAnalysisExperiment = - bool.fromEnvironment('memory_analysis_experiment'); +const bool kMemoryOfflineExperiment = + bool.fromEnvironment('memory_offline_experiment'); // It is ok to have enum-like static only classes. // ignore: avoid_classes_with_only_static_members @@ -59,8 +59,8 @@ abstract class FeatureFlags { /// Flag to enable offline data on memory screen. /// /// https://github.com/flutter/devtools/issues/5606 - static bool memoryAnalysis = - kMemoryAnalysisExperiment; // requires special handling because it needs to be const + static bool memoryOffline = + kMemoryOfflineExperiment; // requires special handling because it needs to be const /// Flag to enable the deep link validation tooling in DevTools, both for the /// DevTools screen and the standalone tool for IDE embedding. diff --git a/packages/devtools_app/lib/src/shared/screen.dart b/packages/devtools_app/lib/src/shared/screen.dart index 60cb60839c0..24c34ae8064 100644 --- a/packages/devtools_app/lib/src/shared/screen.dart +++ b/packages/devtools_app/lib/src/shared/screen.dart @@ -57,7 +57,7 @@ enum ScreenMetaData { requiresDartVm: true, tutorialVideoTimestamp: '?t=420', // ignore: avoid_redundant_argument_values, false positive - worksWithOfflineData: kMemoryAnalysisExperiment, + worksWithOfflineData: kMemoryOfflineExperiment, ), debugger( 'debugger', From ea47bc9a8c032c66711d46e096453601e17afe39 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 12:55:47 -0700 Subject: [PATCH 04/97] - --- packages/devtools_app/lib/src/shared/feature_flags.dart | 6 +++--- packages/devtools_app/lib/src/shared/screen.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index 4a74523641e..9b437fad31b 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -35,7 +35,7 @@ void setEnableExperiments() { @visibleForTesting bool get enableBeta => enableExperiments || !isExternalBuild; -const bool kMemoryOfflineExperiment = +const bool _kMemoryOfflineExperiment = bool.fromEnvironment('memory_offline_experiment'); // It is ok to have enum-like static only classes. @@ -59,8 +59,8 @@ abstract class FeatureFlags { /// Flag to enable offline data on memory screen. /// /// https://github.com/flutter/devtools/issues/5606 - static bool memoryOffline = - kMemoryOfflineExperiment; // requires special handling because it needs to be const + static const bool memoryOffline = + _kMemoryOfflineExperiment; // requires special handling because it needs to be const /// Flag to enable the deep link validation tooling in DevTools, both for the /// DevTools screen and the standalone tool for IDE embedding. diff --git a/packages/devtools_app/lib/src/shared/screen.dart b/packages/devtools_app/lib/src/shared/screen.dart index 24c34ae8064..cfee9c6789b 100644 --- a/packages/devtools_app/lib/src/shared/screen.dart +++ b/packages/devtools_app/lib/src/shared/screen.dart @@ -57,7 +57,7 @@ enum ScreenMetaData { requiresDartVm: true, tutorialVideoTimestamp: '?t=420', // ignore: avoid_redundant_argument_values, false positive - worksWithOfflineData: kMemoryOfflineExperiment, + worksWithOfflineData: FeatureFlags.memoryOffline, ), debugger( 'debugger', From 3bbed408beb4ba25193fe1c5336f47a66d552fea Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 14:59:17 -0700 Subject: [PATCH 05/97] Update launch.json --- packages/.vscode/launch.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/.vscode/launch.json b/packages/.vscode/launch.json index b9b6201c12d..c61274d1f7f 100644 --- a/packages/.vscode/launch.json +++ b/packages/.vscode/launch.json @@ -24,6 +24,7 @@ "args": [ "--dart-define", "memory_offline_experiment=true", + "--dart-define", "enable_experiments=true", ], }, From 215ed02d39a155706ad8d06c7f72f020a3814138 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 15:51:54 -0700 Subject: [PATCH 06/97] - --- .../connected/memory_controller.dart | 31 ++++++++++++++++--- .../framework/offline_data/offline_data.dart | 5 +++ .../controller/control_pane_controller.dart | 6 +++- .../control/widgets/secondary_controls.dart | 7 +++++ 4 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index c397c9a1b83..9870b19d87d 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -9,28 +9,34 @@ import 'package:flutter/foundation.dart'; import '../../../../shared/memory/class_name.dart'; import '../../../../shared/memory/heap_graph_loader.dart'; +import '../../../../shared/offline_data.dart'; import '../../panes/chart/controller/chart_pane_controller.dart'; import '../../panes/control/controller/control_pane_controller.dart'; import '../../panes/diff/controller/diff_pane_controller.dart'; import '../../panes/profile/profile_pane_controller.dart'; import '../../panes/tracing/tracing_pane_controller.dart'; +import '../offline_data/offline_data.dart'; class MemoryFeatureControllers { /// Controllers are passed for testability. MemoryFeatureControllers( DiffPaneController? diffPaneController, - ProfilePaneController? profilePaneController, - ) { + ProfilePaneController? profilePaneController, { + required VoidCallback exportData, + }) { diff = diffPaneController ?? _createDiffController(); profile = profilePaneController ?? ProfilePaneController(); + control = MemoryControlPaneController( + chart.memoryTimeline, + exportData: exportData, + ); } late DiffPaneController diff; late ProfilePaneController profile; late MemoryChartPaneController chart = MemoryChartPaneController(); TracingPaneController tracing = TracingPaneController(); - late final MemoryControlPaneController control = - MemoryControlPaneController(chart.memoryTimeline); + late final MemoryControlPaneController control; DiffPaneController _createDiffController() => DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); @@ -63,7 +69,9 @@ class MemoryFeatureControllers { /// /// The controller should be recreated for every new connection. class MemoryController extends DisposableController - with AutoDisposeControllerMixin { + with + AutoDisposeControllerMixin, + OfflineScreenControllerMixin { MemoryController({ @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, @@ -71,6 +79,7 @@ class MemoryController extends DisposableController controllers = MemoryFeatureControllers( diffPaneController, profilePaneController, + exportData: exportData, ); shareClassFilterBetweenProfileAndDiff(); } @@ -111,4 +120,16 @@ class MemoryController extends DisposableController controllers.dispose(); HeapClassName.dispose(); } + + @override + OfflineScreenData prepareOfflineScreenData() { + // TODO: implement prepareOfflineScreenData + throw UnimplementedError(); + } + + @override + FutureOr processOfflineData(OfflineMemoryData offlineData) { + // TODO: implement processOfflineData + throw UnimplementedError(); + } } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart new file mode 100644 index 00000000000..b65948faa73 --- /dev/null +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -0,0 +1,5 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +class OfflineMemoryData {} diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart index 1b21be2e56c..1ded622b30e 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart @@ -2,13 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; + import '../../../../../shared/globals.dart'; import '../../../shared/primitives/memory_timeline.dart'; class MemoryControlPaneController { - MemoryControlPaneController(this.memoryTimeline); + MemoryControlPaneController(this.memoryTimeline, {required this.exportData}); final MemoryTimeline memoryTimeline; + final VoidCallback exportData; + bool get isGcing => _gcing; bool _gcing = false; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/secondary_controls.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/secondary_controls.dart index 2d43a1881a8..85de97c8147 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/secondary_controls.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/secondary_controls.dart @@ -9,6 +9,8 @@ import 'package:flutter/material.dart'; import '../../../../../shared/analytics/constants.dart' as gac; import '../../../../../shared/common_widgets.dart'; +import '../../../../../shared/file_import.dart'; +import '../../../../../shared/screen.dart'; import '../../../shared/primitives/simple_elements.dart'; import '../controller/control_pane_controller.dart'; import 'settings_dialog.dart'; @@ -37,6 +39,11 @@ class SecondaryControls extends StatelessWidget { gaSelection: gac.MemoryEvent.gc, ), const SizedBox(width: denseSpacing), + OpenSaveButtonGroup( + screenId: ScreenMetaData.memory.id, + onSave: controller.exportData, + ), + const SizedBox(width: denseSpacing), SettingsOutlinedButton( gaScreen: gac.memory, gaSelection: gac.MemoryEvent.settings, From dc0844f391432ab3103ec10d7ffad87b3bbcfa25 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 16:03:41 -0700 Subject: [PATCH 07/97] - --- .../connected/memory_controller.dart | 22 ++++++++++++------- .../framework/offline_data/offline_data.dart | 6 ++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index 9870b19d87d..58d556c5ab4 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -6,7 +6,9 @@ import 'dart:async'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; +import 'package:web/helpers.dart'; +import '../../../../../devtools_app.dart'; import '../../../../shared/memory/class_name.dart'; import '../../../../shared/memory/heap_graph_loader.dart'; import '../../../../shared/offline_data.dart'; @@ -122,14 +124,18 @@ class MemoryController extends DisposableController } @override - OfflineScreenData prepareOfflineScreenData() { - // TODO: implement prepareOfflineScreenData - throw UnimplementedError(); - } + OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( + screenId: MemoryScreen.id, + data: OfflineMemoryData().toJson(), + // { + // // 'selectedTab: selectedFeatureTabIndex, + // // 'diffData': controllers.diff.prepareForOffline(), + // // 'profileData': controllers.profile.prepareForOffline(), + // // 'chartData': controllers.chart.prepareForOffline(), + // // 'controlData': controllers.control.prepareForOffline(), + // }, + ); @override - FutureOr processOfflineData(OfflineMemoryData offlineData) { - // TODO: implement processOfflineData - throw UnimplementedError(); - } + FutureOr processOfflineData(OfflineMemoryData offlineData) {} } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index b65948faa73..ccf8e1b7996 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -2,4 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -class OfflineMemoryData {} +class OfflineMemoryData { + Map toJson() { + return {}; + } +} From b6e8225e901477a2697106c5d128f71e84f96a2c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 16:41:27 -0700 Subject: [PATCH 08/97] Update memory_controller.dart --- .../connected/memory_controller.dart | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index 0efc107dee2..a177800a438 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -2,16 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; +import 'dart:math'; + import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; +import '../../../../../devtools_app.dart'; import '../../../../shared/memory/class_name.dart'; import '../../../../shared/memory/heap_graph_loader.dart'; +import '../../../../shared/offline_data.dart'; import '../../panes/chart/controller/chart_pane_controller.dart'; import '../../panes/control/controller/control_pane_controller.dart'; import '../../panes/diff/controller/diff_pane_controller.dart'; import '../../panes/profile/profile_pane_controller.dart'; import '../../panes/tracing/tracing_pane_controller.dart'; +import '../offline_data/offline_data.dart'; /// This class contains the business logic for memory screen, for a connected /// application. @@ -21,7 +27,9 @@ import '../../panes/tracing/tracing_pane_controller.dart'; /// /// The controller should be recreated for every new connection. class MemoryController extends DisposableController - with AutoDisposeControllerMixin { + with + AutoDisposeControllerMixin, + OfflineScreenControllerMixin { MemoryController({ @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, @@ -45,7 +53,7 @@ class MemoryController extends DisposableController late MemoryChartPaneController chart = MemoryChartPaneController(); TracingPaneController tracing = TracingPaneController(); late final MemoryControlPaneController control = - MemoryControlPaneController(chart.memoryTimeline); + MemoryControlPaneController(chart.memoryTimeline, exportData: exportData); @override void dispose() { @@ -88,4 +96,20 @@ class MemoryController extends DisposableController ); }); } + + @override + OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( + screenId: ScreenMetaData.memory.id, + data: OfflineMemoryData().toJson(), + // { + // // 'selectedTab: selectedFeatureTabIndex, + // // 'diffData': controllers.diff.prepareForOffline(), + // // 'profileData': controllers.profile.prepareForOffline(), + // // 'chartData': controllers.chart.prepareForOffline(), + // // 'controlData': controllers.control.prepareForOffline(), + // }, + ); + + @override + FutureOr processOfflineData(OfflineMemoryData offlineData) {} } From b73eb28d3288714ac025bec599bc7c2cc4bb0e67 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Apr 2024 16:45:32 -0700 Subject: [PATCH 09/97] Update memory_controller.dart --- .../connected/memory_controller.dart | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index a177800a438..1b4285c1e95 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:math'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; @@ -11,7 +10,6 @@ import 'package:flutter/foundation.dart'; import '../../../../../devtools_app.dart'; import '../../../../shared/memory/class_name.dart'; import '../../../../shared/memory/heap_graph_loader.dart'; -import '../../../../shared/offline_data.dart'; import '../../panes/chart/controller/chart_pane_controller.dart'; import '../../panes/control/controller/control_pane_controller.dart'; import '../../panes/diff/controller/diff_pane_controller.dart'; @@ -34,10 +32,11 @@ class MemoryController extends DisposableController @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, }) { - diff = diffPaneController ?? _createDiffController(); + diff = diffPaneController ?? + DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); profile = profilePaneController ?? ProfilePaneController(); - shareClassFilterBetweenProfileAndDiff(); + _shareClassFilterBetweenProfileAndDiff(); } /// Index of the selected feature tab. @@ -65,23 +64,7 @@ class MemoryController extends DisposableController profile.dispose(); } - DiffPaneController _createDiffController() => - DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); - - void reset() { - diff.dispose(); - diff = _createDiffController(); - - profile.dispose(); - profile = ProfilePaneController(); - - tracing.dispose(); - tracing = TracingPaneController(); - - chart.memoryTimeline.reset(); - } - - void shareClassFilterBetweenProfileAndDiff() { + void _shareClassFilterBetweenProfileAndDiff() { diff.derived.applyFilter( profile.classFilter.value, ); From 5067dbc941d8797d8eafd1d295f3d722b587214b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 10:53:08 -0700 Subject: [PATCH 10/97] - --- .../connected/memory_controller.dart | 61 +++++++++++++------ .../framework/offline_data/offline_data.dart | 42 ++++++++++++- .../controller/chart_pane_controller.dart | 4 ++ .../diff/controller/diff_pane_controller.dart | 4 ++ .../profile/profile_pane_controller.dart | 4 ++ 5 files changed, 96 insertions(+), 19 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index 1b4285c1e95..f4ab50aef6b 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; import '../../../../../devtools_app.dart'; import '../../../../shared/memory/class_name.dart'; @@ -32,13 +33,11 @@ class MemoryController extends DisposableController @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, }) { - diff = diffPaneController ?? - DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); - profile = profilePaneController ?? ProfilePaneController(); - - _shareClassFilterBetweenProfileAndDiff(); + unawaited(_init(diffPaneController, profilePaneController)); } + ValueNotifier isInitialized = ValueNotifier(false); + /// Index of the selected feature tab. /// /// This value is used to set the initial tab selection of the @@ -47,12 +46,18 @@ class MemoryController extends DisposableController /// instead of the widget state. int selectedFeatureTabIndex = 0; - late DiffPaneController diff; + late final DiffPaneController diff; + late ProfilePaneController profile; - late MemoryChartPaneController chart = MemoryChartPaneController(); - TracingPaneController tracing = TracingPaneController(); - late final MemoryControlPaneController control = - MemoryControlPaneController(chart.memoryTimeline, exportData: exportData); + + late final MemoryChartPaneController chart = MemoryChartPaneController(); + + final TracingPaneController tracing = TracingPaneController(); + + late final MemoryControlPaneController control = MemoryControlPaneController( + chart.memoryTimeline, + exportData: exportData, + ); @override void dispose() { @@ -64,6 +69,28 @@ class MemoryController extends DisposableController profile.dispose(); } + Future _init( + @visibleForTesting DiffPaneController? diffPaneController, + @visibleForTesting ProfilePaneController? profilePaneController, + ) async { + final showingOfflineData = offlineDataController.showingOfflineData.value; + + if (showingOfflineData) { + await maybeLoadOfflineData( + PerformanceScreen.id, + createData: (json) => OfflineMemoryData.parse(json), + shouldLoad: (data) => !data.isEmpty, + ); + } else { + diff = diffPaneController ?? + DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); + profile = profilePaneController ?? ProfilePaneController(); + } + + _shareClassFilterBetweenProfileAndDiff(); + isInitialized.value = true; + } + void _shareClassFilterBetweenProfileAndDiff() { diff.derived.applyFilter( profile.classFilter.value, @@ -83,14 +110,12 @@ class MemoryController extends DisposableController @override OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( screenId: ScreenMetaData.memory.id, - data: OfflineMemoryData().toJson(), - // { - // // 'selectedTab: selectedFeatureTabIndex, - // // 'diffData': controllers.diff.prepareForOffline(), - // // 'profileData': controllers.profile.prepareForOffline(), - // // 'chartData': controllers.chart.prepareForOffline(), - // // 'controlData': controllers.control.prepareForOffline(), - // }, + data: OfflineMemoryData( + diff, + profile, + chart, + selectedTab: selectedFeatureTabIndex, + ).toJson(), ); @override diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index ccf8e1b7996..6e312540319 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -2,8 +2,48 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import '../../panes/chart/controller/chart_pane_controller.dart'; +import '../../panes/diff/controller/diff_pane_controller.dart'; +import '../../panes/profile/profile_pane_controller.dart'; + +class _Json { + static const selectedTab = 'selectedTab'; + static const diffData = 'diffData'; + static const profileData = 'profileData'; + static const chartData = 'chartData'; +} + class OfflineMemoryData { + OfflineMemoryData( + this.diff, + this.profile, + this.chart, { + required this.selectedTab, + }); + + factory OfflineMemoryData.parse(Map json) { + throw UnimplementedError(); + // return OfflineMemoryData( + // selectedTab: json[_Json.selectedTab] as int, + // diffData: json[_Json.diffData] as Map, + // profileData: json[_Json.profileData] as Map, + // chartData: json[_Json.chartData] as Map, + // ); + } + + bool isEmpty = false; + + final DiffPaneController diff; + final ProfilePaneController profile; + final MemoryChartPaneController chart; + final int selectedTab; + Map toJson() { - return {}; + return { + _Json.selectedTab: selectedTab, + _Json.diffData: diff.prepareForOffline(), + _Json.profileData: profile.prepareForOffline(), + _Json.chartData: chart.prepareForOffline(), + }; } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index c72e7925e04..76fec8ef827 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -224,4 +224,8 @@ class MemoryChartPaneController extends DisposableController android.dispose(); isAndroidChartVisible.dispose(); } + + Map prepareForOffline() { + return {}; + } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart index ca7138883ba..b8fd3099617 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart @@ -166,6 +166,10 @@ class DiffPaneController extends DisposableController { ), ); } + + Map prepareForOffline() { + return {}; + } } /// Values that define what data to show on diff screen. diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 28eb2dedd70..9fe011d9329 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -169,4 +169,8 @@ class ProfilePaneController extends DisposableController type: ExportFileType.csv, ); } + + Map prepareForOffline() { + return {}; + } } From c31d0511f79e57c1310b1cf349ac7ad51e0bf517 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 11:05:09 -0700 Subject: [PATCH 11/97] Update memory_controller.dart --- .../framework/connected/memory_controller.dart | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart index f4ab50aef6b..f477f430b70 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart @@ -48,16 +48,13 @@ class MemoryController extends DisposableController late final DiffPaneController diff; - late ProfilePaneController profile; + late final ProfilePaneController profile; - late final MemoryChartPaneController chart = MemoryChartPaneController(); + late final MemoryChartPaneController chart; - final TracingPaneController tracing = TracingPaneController(); + late final TracingPaneController tracing; - late final MemoryControlPaneController control = MemoryControlPaneController( - chart.memoryTimeline, - exportData: exportData, - ); + late final MemoryControlPaneController control; @override void dispose() { @@ -76,6 +73,7 @@ class MemoryController extends DisposableController final showingOfflineData = offlineDataController.showingOfflineData.value; if (showingOfflineData) { + // Triggers `processOfflineData`, that initializes all the controllers. await maybeLoadOfflineData( PerformanceScreen.id, createData: (json) => OfflineMemoryData.parse(json), @@ -85,6 +83,12 @@ class MemoryController extends DisposableController diff = diffPaneController ?? DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); profile = profilePaneController ?? ProfilePaneController(); + chart = MemoryChartPaneController(); + tracing = TracingPaneController(); + control = MemoryControlPaneController( + chart.memoryTimeline, + exportData: exportData, + ); } _shareClassFilterBetweenProfileAndDiff(); From 51a189a1592cfdd45da78307cbd9c135317dab9f Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 12:39:54 -0700 Subject: [PATCH 12/97] - --- packages/devtools_app/lib/devtools_app.dart | 2 +- packages/devtools_app/lib/src/app.dart | 2 +- .../memory/framework/connected/DEPENDENCIES.md | 17 ----------------- .../{connected => }/connected_screen_body.dart | 12 ++++++------ .../{connected => }/memory_controller.dart | 18 +++++++++--------- .../memory/framework/memory_screen.dart | 2 +- .../framework/{connected => }/memory_tabs.dart | 12 ++++++------ .../memory/diff/widgets/diff_pane_test.dart | 2 +- .../framework/memory_controller_test.dart | 2 +- .../memory/framework/memory_service_test.dart | 2 +- .../allocation_profile_table_view_test.dart | 2 +- .../test/memory/tracing/tracing_view_test.dart | 2 +- 12 files changed, 29 insertions(+), 46 deletions(-) delete mode 100644 packages/devtools_app/lib/src/screens/memory/framework/connected/DEPENDENCIES.md rename packages/devtools_app/lib/src/screens/memory/framework/{connected => }/connected_screen_body.dart (85%) rename packages/devtools_app/lib/src/screens/memory/framework/{connected => }/memory_controller.dart (87%) rename packages/devtools_app/lib/src/screens/memory/framework/{connected => }/memory_tabs.dart (87%) diff --git a/packages/devtools_app/lib/devtools_app.dart b/packages/devtools_app/lib/devtools_app.dart index ae650c01e10..3f572827f55 100644 --- a/packages/devtools_app/lib/devtools_app.dart +++ b/packages/devtools_app/lib/devtools_app.dart @@ -26,7 +26,7 @@ export 'src/screens/inspector/inspector_screen.dart'; export 'src/screens/inspector/inspector_tree_controller.dart'; export 'src/screens/logging/logging_controller.dart'; export 'src/screens/logging/logging_screen.dart'; -export 'src/screens/memory/framework/connected/memory_controller.dart'; +export 'src/screens/memory/framework/memory_controller.dart'; export 'src/screens/memory/framework/memory_screen.dart'; export 'src/screens/network/network_controller.dart'; export 'src/screens/network/network_model.dart'; diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index 2bec2e4b57f..17b0b66104a 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -29,7 +29,7 @@ import 'screens/inspector/inspector_screen.dart'; import 'screens/inspector/inspector_tree_controller.dart'; import 'screens/logging/logging_controller.dart'; import 'screens/logging/logging_screen.dart'; -import 'screens/memory/framework/connected/memory_controller.dart'; +import 'screens/memory/framework/memory_controller.dart'; import 'screens/memory/framework/memory_screen.dart'; import 'screens/network/network_controller.dart'; import 'screens/network/network_screen.dart'; diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/DEPENDENCIES.md b/packages/devtools_app/lib/src/screens/memory/framework/connected/DEPENDENCIES.md deleted file mode 100644 index 4abb6fde384..00000000000 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/DEPENDENCIES.md +++ /dev/null @@ -1,17 +0,0 @@ - - -```mermaid -flowchart TD; -connected_screen_body.dart-->memory_controller.dart; -connected_screen_body.dart-->memory_tabs.dart; -memory_tabs.dart-->memory_controller.dart; -``` - -### Inversions -In this folder: 0 - -Including sub-folders: 0 - diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/connected_screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/connected_screen_body.dart similarity index 85% rename from packages/devtools_app/lib/src/screens/memory/framework/connected/connected_screen_body.dart rename to packages/devtools_app/lib/src/screens/memory/framework/connected_screen_body.dart index d7a6c375ada..381c70ba7f7 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/connected_screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/connected_screen_body.dart @@ -6,12 +6,12 @@ import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/material.dart'; -import '../../../../shared/banner_messages.dart'; -import '../../../../shared/http/http_service.dart' as http_service; -import '../../../../shared/screen.dart'; -import '../../../../shared/utils.dart'; -import '../../panes/chart/widgets/chart_pane.dart'; -import '../../panes/control/widgets/control_pane.dart'; +import '../../../shared/banner_messages.dart'; +import '../../../shared/http/http_service.dart' as http_service; +import '../../../shared/screen.dart'; +import '../../../shared/utils.dart'; +import '../panes/chart/widgets/chart_pane.dart'; +import '../panes/control/widgets/control_pane.dart'; import 'memory_controller.dart'; import 'memory_tabs.dart'; diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart similarity index 87% rename from packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart rename to packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index f477f430b70..db0e760810a 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -8,15 +8,15 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; -import '../../../../../devtools_app.dart'; -import '../../../../shared/memory/class_name.dart'; -import '../../../../shared/memory/heap_graph_loader.dart'; -import '../../panes/chart/controller/chart_pane_controller.dart'; -import '../../panes/control/controller/control_pane_controller.dart'; -import '../../panes/diff/controller/diff_pane_controller.dart'; -import '../../panes/profile/profile_pane_controller.dart'; -import '../../panes/tracing/tracing_pane_controller.dart'; -import '../offline_data/offline_data.dart'; +import '../../../../devtools_app.dart'; +import '../../../shared/memory/class_name.dart'; +import '../../../shared/memory/heap_graph_loader.dart'; +import '../panes/chart/controller/chart_pane_controller.dart'; +import '../panes/control/controller/control_pane_controller.dart'; +import '../panes/diff/controller/diff_pane_controller.dart'; +import '../panes/profile/profile_pane_controller.dart'; +import '../panes/tracing/tracing_pane_controller.dart'; +import 'offline_data/offline_data.dart'; /// This class contains the business logic for memory screen, for a connected /// application. diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart index 8132e94b51a..fc982fc277a 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import '../../../shared/analytics/analytics.dart' as ga; import '../../../shared/primitives/listenable.dart'; import '../../../shared/screen.dart'; -import 'connected/connected_screen_body.dart'; +import 'connected_screen_body.dart'; class MemoryScreen extends Screen { MemoryScreen() : super.fromMetaData(ScreenMetaData.memory); diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_tabs.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart similarity index 87% rename from packages/devtools_app/lib/src/screens/memory/framework/connected/memory_tabs.dart rename to packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart index dd5bb4332bb..57d868e774c 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/connected/memory_tabs.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_tabs.dart @@ -4,12 +4,12 @@ import 'package:flutter/material.dart'; -import '../../../../shared/analytics/constants.dart' as gac; -import '../../../../shared/common_widgets.dart'; -import '../../../../shared/ui/tab.dart'; -import '../../panes/diff/diff_pane.dart'; -import '../../panes/profile/profile_view.dart'; -import '../../panes/tracing/tracing_view.dart'; +import '../../../shared/analytics/constants.dart' as gac; +import '../../../shared/common_widgets.dart'; +import '../../../shared/ui/tab.dart'; +import '../panes/diff/diff_pane.dart'; +import '../panes/profile/profile_view.dart'; +import '../panes/tracing/tracing_view.dart'; import 'memory_controller.dart'; @visibleForTesting diff --git a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart index 80d9262209d..532955a01de 100644 --- a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart +++ b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:devtools_app/devtools_app.dart'; -import 'package:devtools_app/src/screens/memory/framework/connected/memory_tabs.dart'; +import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/panes/diff/diff_pane.dart'; import 'package:devtools_app/src/screens/memory/panes/diff/widgets/snapshot_list.dart'; import 'package:devtools_test/helpers.dart'; diff --git a/packages/devtools_app/test/memory/framework/memory_controller_test.dart b/packages/devtools_app/test/memory/framework/memory_controller_test.dart index 127cf02eddf..b9d426bd165 100644 --- a/packages/devtools_app/test/memory/framework/memory_controller_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_controller_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:devtools_app/devtools_app.dart'; -import 'package:devtools_app/src/screens/memory/framework/connected/memory_tabs.dart'; +import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/shared/heap/class_filter.dart'; import 'package:devtools_test/helpers.dart'; import 'package:flutter/material.dart'; diff --git a/packages/devtools_app/test/memory/framework/memory_service_test.dart b/packages/devtools_app/test/memory/framework/memory_service_test.dart index 9395443c75a..31fadd97066 100644 --- a/packages/devtools_app/test/memory/framework/memory_service_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_service_test.dart @@ -5,7 +5,7 @@ @TestOn('vm') import 'dart:async'; -import 'package:devtools_app/src/screens/memory/framework/connected/memory_controller.dart'; +import 'package:devtools_app/src/screens/memory/framework/memory_controller.dart'; import 'package:devtools_app/src/screens/memory/panes/chart/controller/memory_tracker.dart'; import 'package:devtools_app/src/screens/memory/shared/primitives/memory_timeline.dart'; import 'package:devtools_app/src/shared/globals.dart'; diff --git a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart index 58cf14a7890..495cc66b163 100644 --- a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart +++ b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:devtools_app/src/screens/memory/framework/connected/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/framework/memory_screen.dart'; +import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/panes/profile/model.dart'; import 'package:devtools_app/src/screens/memory/panes/profile/profile_pane_controller.dart'; import 'package:devtools_app/src/screens/vm_developer/vm_service_private_extensions.dart'; diff --git a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart index 58a79611309..52b0483468f 100644 --- a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart +++ b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart @@ -6,7 +6,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:devtools_app/devtools_app.dart'; -import 'package:devtools_app/src/screens/memory/framework/connected/memory_tabs.dart'; +import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/panes/tracing/tracing_pane_controller.dart'; import 'package:devtools_app/src/screens/memory/panes/tracing/tracing_tree.dart'; import 'package:devtools_app_shared/utils.dart'; From 63daf746927e2bc6078266288f5c25e513b332f2 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 12:41:19 -0700 Subject: [PATCH 13/97] Update DEPENDENCIES.md --- .../lib/src/screens/memory/framework/DEPENDENCIES.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md b/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md index dae5e6956a7..3aa4ca25f3a 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md +++ b/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md @@ -5,7 +5,11 @@ Dependencies that create loops (inversions) are marked with `!`. ```mermaid flowchart TD; -memory_screen.dart-->connected; +connected_screen_body.dart-->memory_controller.dart; +connected_screen_body.dart-->memory_tabs.dart; +memory_controller.dart-->offline_data; +memory_screen.dart-->connected_screen_body.dart; +memory_tabs.dart-->memory_controller.dart; ``` ### Inversions From aeeba2dd048e330169ae0205556914b70a280c48 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 12:46:51 -0700 Subject: [PATCH 14/97] - --- .../lib/src/screens/memory/framework/memory_screen.dart | 2 +- .../framework/{connected_screen_body.dart => screen_body.dart} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/devtools_app/lib/src/screens/memory/framework/{connected_screen_body.dart => screen_body.dart} (100%) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart index fc982fc277a..9c88823fae6 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_screen.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import '../../../shared/analytics/analytics.dart' as ga; import '../../../shared/primitives/listenable.dart'; import '../../../shared/screen.dart'; -import 'connected_screen_body.dart'; +import 'screen_body.dart'; class MemoryScreen extends Screen { MemoryScreen() : super.fromMetaData(ScreenMetaData.memory); diff --git a/packages/devtools_app/lib/src/screens/memory/framework/connected_screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart similarity index 100% rename from packages/devtools_app/lib/src/screens/memory/framework/connected_screen_body.dart rename to packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart From 08de780650f04b057485969f16e060ab01650e79 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 13:14:54 -0700 Subject: [PATCH 15/97] - --- .../src/screens/memory/framework/DEPENDENCIES.md | 6 +++--- .../panes/profile/profile_pane_controller.dart | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md b/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md index 3aa4ca25f3a..60293457965 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md +++ b/packages/devtools_app/lib/src/screens/memory/framework/DEPENDENCIES.md @@ -5,11 +5,11 @@ Dependencies that create loops (inversions) are marked with `!`. ```mermaid flowchart TD; -connected_screen_body.dart-->memory_controller.dart; -connected_screen_body.dart-->memory_tabs.dart; memory_controller.dart-->offline_data; -memory_screen.dart-->connected_screen_body.dart; +memory_screen.dart-->screen_body.dart; memory_tabs.dart-->memory_controller.dart; +screen_body.dart-->memory_controller.dart; +screen_body.dart-->memory_tabs.dart; ``` ### Inversions diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 9fe011d9329..71aa44d253a 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -15,6 +15,18 @@ import 'model.dart'; class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin { + ProfilePaneController(); + + ProfilePaneController._(); + + factory ProfilePaneController.forOfflineData(Map json) { + return ProfilePaneController._(); + } + + Map prepareForOffline() { + return {}; + } + final _exportController = ExportController(); /// The current profile being displayed. @@ -169,8 +181,4 @@ class ProfilePaneController extends DisposableController type: ExportFileType.csv, ); } - - Map prepareForOffline() { - return {}; - } } From 3ca3cd14976566ee7f071bea319ff91ae15caa23 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Apr 2024 14:56:56 -0700 Subject: [PATCH 16/97] Update memory_controller.dart --- .../src/screens/memory/framework/memory_controller.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index db0e760810a..5ebe259c638 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -123,5 +123,12 @@ class MemoryController extends DisposableController ); @override - FutureOr processOfflineData(OfflineMemoryData offlineData) {} + FutureOr processOfflineData(OfflineMemoryData offlineData) { + assert(!isInitialized.value); + diff = offlineData.diff; + profile = offlineData.profile; + chart = offlineData.chart; + selectedFeatureTabIndex = offlineData.selectedTab; + tracing = TracingPaneController(); + } } From bcc02465c2b596223c02705045459d61dfc2c904 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Apr 2024 13:12:51 -0700 Subject: [PATCH 17/97] - --- .../memory/framework/memory_controller.dart | 4 +++- .../framework/offline_data/offline_data.dart | 16 +++++++++------- .../controller/chart_pane_controller.dart | 12 ++++++++---- .../diff/controller/diff_pane_controller.dart | 19 ++++++++++++------- .../profile/profile_pane_controller.dart | 6 ++---- .../test_infra/scenes/memory/default.dart | 2 +- .../scenes/memory/diff_snapshot.dart | 2 +- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 5ebe259c638..30d47fd4832 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -81,7 +81,9 @@ class MemoryController extends DisposableController ); } else { diff = diffPaneController ?? - DiffPaneController(HeapGraphLoaderRuntime(chart.memoryTimeline)); + DiffPaneController( + loader: HeapGraphLoaderRuntime(chart.memoryTimeline), + ); profile = profilePaneController ?? ProfilePaneController(); chart = MemoryChartPaneController(); tracing = TracingPaneController(); diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index 6e312540319..c5d7ce6ab20 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -22,13 +22,15 @@ class OfflineMemoryData { }); factory OfflineMemoryData.parse(Map json) { - throw UnimplementedError(); - // return OfflineMemoryData( - // selectedTab: json[_Json.selectedTab] as int, - // diffData: json[_Json.diffData] as Map, - // profileData: json[_Json.profileData] as Map, - // chartData: json[_Json.chartData] as Map, - // ); + return OfflineMemoryData( + DiffPaneController.parse( + json[_Json.diffData] as Map? ?? {}), + ProfilePaneController.parse( + json[_Json.profileData] as Map? ?? {}), + MemoryChartPaneController.parse( + json[_Json.chartData] as Map? ?? {}), + selectedTab: json[_Json.selectedTab] as int? ?? 0, + ); } bool isEmpty = false; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 76fec8ef827..396bdd563d1 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -20,6 +20,14 @@ class MemoryChartPaneController extends DisposableController with AutoDisposeControllerMixin { MemoryChartPaneController(); + factory MemoryChartPaneController.parse(Map map) { + return MemoryChartPaneController(); + } + + Map prepareForOffline() { + return {}; + } + final MemoryTimeline memoryTimeline = MemoryTimeline(); late final EventChartController event = @@ -224,8 +232,4 @@ class MemoryChartPaneController extends DisposableController android.dispose(); isAndroidChartVisible.dispose(); } - - Map prepareForOffline() { - return {}; - } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart index b8fd3099617..26217d9a180 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart @@ -29,9 +29,17 @@ import 'class_data.dart'; import 'item_controller.dart'; class DiffPaneController extends DisposableController { - DiffPaneController(this._heapGraphLoader); + DiffPaneController({required this.loader}); - final HeapGraphLoader _heapGraphLoader; + factory DiffPaneController.parse(Map map) { + return DiffPaneController(loader: null); + } + + Map prepareForOffline() { + return {}; + } + + final HeapGraphLoader? loader; final retainingPathController = RetainingPathController(); @@ -43,6 +51,7 @@ class DiffPaneController extends DisposableController { bool get hasSnapshots => core.snapshots.value.length > 1; Future takeSnapshot() async { + final loader = this.loader!; ga.select( gac.memory, gac.MemoryEvent.diffTakeSnapshotControlPane, @@ -53,7 +62,7 @@ class DiffPaneController extends DisposableController { defaultName: selectedIsolateName ?? '', ); - await _addSnapshot(_heapGraphLoader, item); + await _addSnapshot(loader, item); derived._updateValues(); } @@ -166,10 +175,6 @@ class DiffPaneController extends DisposableController { ), ); } - - Map prepareForOffline() { - return {}; - } } /// Values that define what data to show on diff screen. diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 71aa44d253a..07a2ff7cb85 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -17,10 +17,8 @@ class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin { ProfilePaneController(); - ProfilePaneController._(); - - factory ProfilePaneController.forOfflineData(Map json) { - return ProfilePaneController._(); + factory ProfilePaneController.parse(Map map) { + return ProfilePaneController(); } Map prepareForOffline() { diff --git a/packages/devtools_app/test/test_infra/scenes/memory/default.dart b/packages/devtools_app/test/test_infra/scenes/memory/default.dart index 34084b327d2..c1d01543bf5 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/default.dart @@ -135,7 +135,7 @@ class MemoryDefaultScene extends Scene { ); final diffController = - DiffPaneController(HeapGraphLoaderProvided(heapProviders)) + DiffPaneController(loader: HeapGraphLoaderProvided(heapProviders)) ..derived.applyFilter(showAllFilter); final profileController = ProfilePaneController()..setFilter(showAllFilter); diff --git a/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart b/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart index f99fae0a81b..f264c723c0b 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart @@ -46,7 +46,7 @@ class DiffSnapshotScene extends Scene { ); setGlobal(ServiceConnectionManager, fakeServiceConnection); - diffController = DiffPaneController(HeapGraphLoaderGoldens()); + diffController = DiffPaneController(loader: HeapGraphLoaderGoldens()); setClassFilterToShowAll(); await diffController.takeSnapshot(); From f8f29ce550bcec6e25b3ddf911c93920668fa5aa Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Apr 2024 13:21:57 -0700 Subject: [PATCH 18/97] - --- .../screens/memory/framework/memory_controller.dart | 2 +- .../memory/framework/offline_data/offline_data.dart | 11 +++++++---- .../memory/panes/profile/profile_pane_controller.dart | 4 +--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 30d47fd4832..23ddd6aa2d9 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -121,7 +121,7 @@ class MemoryController extends DisposableController profile, chart, selectedTab: selectedFeatureTabIndex, - ).toJson(), + ).prepareForOffline(), ); @override diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index c5d7ce6ab20..ffe4efac60a 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -24,11 +24,14 @@ class OfflineMemoryData { factory OfflineMemoryData.parse(Map json) { return OfflineMemoryData( DiffPaneController.parse( - json[_Json.diffData] as Map? ?? {}), + json[_Json.diffData] as Map? ?? {}, + ), ProfilePaneController.parse( - json[_Json.profileData] as Map? ?? {}), + json[_Json.profileData] as Map? ?? {}, + ), MemoryChartPaneController.parse( - json[_Json.chartData] as Map? ?? {}), + json[_Json.chartData] as Map? ?? {}, + ), selectedTab: json[_Json.selectedTab] as int? ?? 0, ); } @@ -40,7 +43,7 @@ class OfflineMemoryData { final MemoryChartPaneController chart; final int selectedTab; - Map toJson() { + Map prepareForOffline() { return { _Json.selectedTab: selectedTab, _Json.diffData: diff.prepareForOffline(), diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 07a2ff7cb85..93fa2a81989 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -25,8 +25,6 @@ class ProfilePaneController extends DisposableController return {}; } - final _exportController = ExportController(); - /// The current profile being displayed. ValueListenable get currentAllocationProfile => _currentAllocationProfile; @@ -174,7 +172,7 @@ class ProfilePaneController extends DisposableController ].join(','), ); } - _exportController.downloadFile( + ExportController().downloadFile( csvBuffer.toString(), type: ExportFileType.csv, ); From 39b5695c3867d58482a690af4e3f988215a05770 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Apr 2024 13:40:21 -0700 Subject: [PATCH 19/97] - --- .../memory/framework/memory_controller.dart | 35 ++++++++++--------- .../framework/offline_data/offline_data.dart | 7 ++-- .../profile/profile_pane_controller.dart | 1 + 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 23ddd6aa2d9..61b2af666ab 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -73,7 +73,7 @@ class MemoryController extends DisposableController final showingOfflineData = offlineDataController.showingOfflineData.value; if (showingOfflineData) { - // Triggers `processOfflineData`, that initializes all the controllers. + // Triggers [processOfflineData], that initializes all the controllers. await maybeLoadOfflineData( PerformanceScreen.id, createData: (json) => OfflineMemoryData.parse(json), @@ -97,22 +97,6 @@ class MemoryController extends DisposableController isInitialized.value = true; } - void _shareClassFilterBetweenProfileAndDiff() { - diff.derived.applyFilter( - profile.classFilter.value, - ); - - profile.classFilter.addListener(() { - diff.derived.applyFilter(profile.classFilter.value); - }); - - diff.core.classFilter.addListener(() { - profile.setFilter( - diff.core.classFilter.value, - ); - }); - } - @override OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( screenId: ScreenMetaData.memory.id, @@ -126,6 +110,7 @@ class MemoryController extends DisposableController @override FutureOr processOfflineData(OfflineMemoryData offlineData) { + assert(offlineDataController.showingOfflineData.value); assert(!isInitialized.value); diff = offlineData.diff; profile = offlineData.profile; @@ -133,4 +118,20 @@ class MemoryController extends DisposableController selectedFeatureTabIndex = offlineData.selectedTab; tracing = TracingPaneController(); } + + void _shareClassFilterBetweenProfileAndDiff() { + diff.derived.applyFilter( + profile.classFilter.value, + ); + + profile.classFilter.addListener(() { + diff.derived.applyFilter(profile.classFilter.value); + }); + + diff.core.classFilter.addListener(() { + profile.setFilter( + diff.core.classFilter.value, + ); + }); + } } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index ffe4efac60a..9deabb715d3 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -18,6 +18,7 @@ class OfflineMemoryData { this.diff, this.profile, this.chart, { + this.isEmpty = false, required this.selectedTab, }); @@ -33,15 +34,17 @@ class OfflineMemoryData { json[_Json.chartData] as Map? ?? {}, ), selectedTab: json[_Json.selectedTab] as int? ?? 0, + isEmpty: json.isEmpty, ); } - bool isEmpty = false; + final bool isEmpty; + + final int selectedTab; final DiffPaneController diff; final ProfilePaneController profile; final MemoryChartPaneController chart; - final int selectedTab; Map prepareForOffline() { return { diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 93fa2a81989..9cd9bb4a6b4 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -18,6 +18,7 @@ class ProfilePaneController extends DisposableController ProfilePaneController(); factory ProfilePaneController.parse(Map map) { + assert(offlineDataController.showingOfflineData.value); return ProfilePaneController(); } From bcd2514756e31154b24075e3ce48fee63c8812b9 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Apr 2024 18:23:25 -0700 Subject: [PATCH 20/97] - --- .../memory/framework/memory_controller.dart | 3 ++ .../framework/offline_data/offline_data.dart | 22 +++++++------- .../memory/shared/heap/class_filter.dart | 30 ++++++++++++++++++- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 61b2af666ab..06c265bdfb3 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -104,6 +104,7 @@ class MemoryController extends DisposableController diff, profile, chart, + profile.classFilter.value, selectedTab: selectedFeatureTabIndex, ).prepareForOffline(), ); @@ -117,6 +118,8 @@ class MemoryController extends DisposableController chart = offlineData.chart; selectedFeatureTabIndex = offlineData.selectedTab; tracing = TracingPaneController(); + profile.setFilter(offlineData.filter); + diff.derived.applyFilter(offlineData.filter); } void _shareClassFilterBetweenProfileAndDiff() { diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index 9deabb715d3..3d36362899a 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -5,9 +5,11 @@ import '../../panes/chart/controller/chart_pane_controller.dart'; import '../../panes/diff/controller/diff_pane_controller.dart'; import '../../panes/profile/profile_pane_controller.dart'; +import '../../shared/heap/class_filter.dart'; class _Json { static const selectedTab = 'selectedTab'; + static const classFilter = 'classFilter'; static const diffData = 'diffData'; static const profileData = 'profileData'; static const chartData = 'chartData'; @@ -17,22 +19,20 @@ class OfflineMemoryData { OfflineMemoryData( this.diff, this.profile, - this.chart, { + this.chart, + this.filter, { this.isEmpty = false, required this.selectedTab, }); factory OfflineMemoryData.parse(Map json) { + Map item(String key) => + json[key] as Map? ?? {}; return OfflineMemoryData( - DiffPaneController.parse( - json[_Json.diffData] as Map? ?? {}, - ), - ProfilePaneController.parse( - json[_Json.profileData] as Map? ?? {}, - ), - MemoryChartPaneController.parse( - json[_Json.chartData] as Map? ?? {}, - ), + DiffPaneController.parse(item(_Json.diffData)), + ProfilePaneController.parse(item(_Json.profileData)), + MemoryChartPaneController.parse(item(_Json.chartData)), + ClassFilter.parse(item(_Json.classFilter)), selectedTab: json[_Json.selectedTab] as int? ?? 0, isEmpty: json.isEmpty, ); @@ -41,6 +41,7 @@ class OfflineMemoryData { final bool isEmpty; final int selectedTab; + final ClassFilter filter; // filter is shared between tabs, so it's here final DiffPaneController diff; final ProfilePaneController profile; @@ -52,6 +53,7 @@ class OfflineMemoryData { _Json.diffData: diff.prepareForOffline(), _Json.profileData: profile.prepareForOffline(), _Json.chartData: chart.prepareForOffline(), + _Json.classFilter: profile.classFilter.value.prepareForOffline(), }; } } diff --git a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart index 7ff9bd6bab0..dee0f81331a 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import '../../../../shared/globals.dart'; @@ -39,6 +40,14 @@ enum FilteringTask { typedef ApplyFilterCallback = void Function(ClassFilter); +class _Json { + static const except = 'except'; + static const only = 'only'; + static const type = 'type'; +} + +const _defaultFilterType = ClassFilterType.except; + @immutable class ClassFilter { ClassFilter({ @@ -50,11 +59,30 @@ class ClassFilter { ClassFilter.empty() : this( - filterType: ClassFilterType.except, + filterType: _defaultFilterType, except: defaultExceptString, only: null, ); + factory ClassFilter.parse(Map json) { + final type = json[_Json.type] as String?; + return ClassFilter( + filterType: + ClassFilterType.values.lastWhereOrNull((t) => t.name == type) ?? + _defaultFilterType, + except: json[_Json.except] as String? ?? defaultExceptString, + only: json[_Json.only] as String?, + ); + } + + Map prepareForOffline() { + return { + _Json.type: filterType.name, + _Json.except: except, + _Json.only: only, + }; + } + @visibleForTesting static final defaultExceptString = '${ClassType.runtime.alias}\n${ClassType.sdk.alias}'; From 0724dbad253bf5bd549ccd0c27536a0c94f0772e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 09:03:36 -0700 Subject: [PATCH 21/97] Update memory_controller.dart --- .../screens/memory/framework/memory_controller.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 06c265bdfb3..c972eb67bf2 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:math'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; @@ -86,13 +87,14 @@ class MemoryController extends DisposableController ); profile = profilePaneController ?? ProfilePaneController(); chart = MemoryChartPaneController(); - tracing = TracingPaneController(); - control = MemoryControlPaneController( - chart.memoryTimeline, - exportData: exportData, - ); } + control = MemoryControlPaneController( + chart.memoryTimeline, + exportData: exportData, + ); + tracing = TracingPaneController(); + _shareClassFilterBetweenProfileAndDiff(); isInitialized.value = true; } @@ -117,7 +119,6 @@ class MemoryController extends DisposableController profile = offlineData.profile; chart = offlineData.chart; selectedFeatureTabIndex = offlineData.selectedTab; - tracing = TracingPaneController(); profile.setFilter(offlineData.filter); diff.derived.applyFilter(offlineData.filter); } From 741f0c44216fbfb84ed0474adf7627f9bcfc4f31 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 10:16:51 -0700 Subject: [PATCH 22/97] Update memory_controller.dart --- .../lib/src/screens/memory/framework/memory_controller.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index c972eb67bf2..6343a6deac5 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:math'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; From 3e28d5c8f3b684339e5f21916aa15a9bf5323ab4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 10:33:11 -0700 Subject: [PATCH 23/97] - --- .../lib/src/screens/memory/framework/memory_controller.dart | 4 +++- .../lib/src/screens/memory/framework/screen_body.dart | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 6343a6deac5..130e4a09226 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -72,6 +72,8 @@ class MemoryController extends DisposableController ) async { final showingOfflineData = offlineDataController.showingOfflineData.value; + print('showingOfflineData: $showingOfflineData'); + if (showingOfflineData) { // Triggers [processOfflineData], that initializes all the controllers. await maybeLoadOfflineData( @@ -80,12 +82,12 @@ class MemoryController extends DisposableController shouldLoad: (data) => !data.isEmpty, ); } else { + chart = MemoryChartPaneController(); diff = diffPaneController ?? DiffPaneController( loader: HeapGraphLoaderRuntime(chart.memoryTimeline), ); profile = profilePaneController ?? ProfilePaneController(); - chart = MemoryChartPaneController(); } control = MemoryControlPaneController( diff --git a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart index 381c70ba7f7..24605f528bd 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart @@ -52,6 +52,12 @@ class _ConnectedMemoryBodyState extends State @override Widget build(BuildContext context) { + if (!memoryController.isInitialized.value) { + return const Center( + child: CircularProgressIndicator(), + ); + } + return Column( key: MemoryChartPane.hoverKey, children: [ From f01ced6b984712e5c1fec0bd5ca461f59d1f62e3 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 12:09:29 -0700 Subject: [PATCH 24/97] Update memory_controller.dart --- .../memory/framework/memory_controller.dart | 66 ++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 130e4a09226..5b56a4bc1aa 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -16,6 +16,7 @@ import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; import '../panes/profile/profile_pane_controller.dart'; import '../panes/tracing/tracing_pane_controller.dart'; +import '../shared/primitives/simple_elements.dart'; import 'offline_data/offline_data.dart'; /// This class contains the business logic for memory screen, for a connected @@ -38,6 +39,12 @@ class MemoryController extends DisposableController ValueNotifier isInitialized = ValueNotifier(false); + /// Mode of memory screen. + /// + /// Is detected at the time of initialization + /// and does not change in lifetime of the controller. + late final MemoryScreenMode mode; + /// Index of the selected feature tab. /// /// This value is used to set the initial tab selection of the @@ -66,29 +73,48 @@ class MemoryController extends DisposableController profile.dispose(); } + bool get _devToolsIsShowingOfflineData => + offlineDataController.showingOfflineData.value; + Future _init( @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, ) async { - final showingOfflineData = offlineDataController.showingOfflineData.value; + if (_devToolsIsShowingOfflineData) { + assert(diffPaneController == null && profilePaneController == null); + await _maybeInitOfflineDataMode(); + if (!isInitialized.value) await _initDisconnectedMode(); + assert(isInitialized.value); + return; + } + await _initConnectedMode(diffPaneController, profilePaneController); + assert(isInitialized.value); + } - print('showingOfflineData: $showingOfflineData'); + Future _maybeInitOfflineDataMode() async { + assert(_devToolsIsShowingOfflineData); + assert(!isInitialized.value); + // Triggers [processOfflineData], that initializes all the controllers. + await maybeLoadOfflineData( + PerformanceScreen.id, + createData: (json) => OfflineMemoryData.parse(json), + shouldLoad: (data) => !data.isEmpty, + ); + } - if (showingOfflineData) { - // Triggers [processOfflineData], that initializes all the controllers. - await maybeLoadOfflineData( - PerformanceScreen.id, - createData: (json) => OfflineMemoryData.parse(json), - shouldLoad: (data) => !data.isEmpty, - ); - } else { - chart = MemoryChartPaneController(); - diff = diffPaneController ?? - DiffPaneController( - loader: HeapGraphLoaderRuntime(chart.memoryTimeline), - ); - profile = profilePaneController ?? ProfilePaneController(); - } + Future _initConnectedMode( + @visibleForTesting DiffPaneController? diffPaneController, + @visibleForTesting ProfilePaneController? profilePaneController, + ) async { + assert(!_devToolsIsShowingOfflineData); + assert(!isInitialized.value); + + chart = MemoryChartPaneController(); + diff = diffPaneController ?? + DiffPaneController( + loader: HeapGraphLoaderRuntime(chart.memoryTimeline), + ); + profile = profilePaneController ?? ProfilePaneController(); control = MemoryControlPaneController( chart.memoryTimeline, @@ -100,6 +126,11 @@ class MemoryController extends DisposableController isInitialized.value = true; } + Future _initDisconnectedMode() async { + assert(!_devToolsIsShowingOfflineData); + assert(!isInitialized.value); + } + @override OfflineScreenData prepareOfflineScreenData() => OfflineScreenData( screenId: ScreenMetaData.memory.id, @@ -122,6 +153,7 @@ class MemoryController extends DisposableController selectedFeatureTabIndex = offlineData.selectedTab; profile.setFilter(offlineData.filter); diff.derived.applyFilter(offlineData.filter); + isInitialized.value = true; } void _shareClassFilterBetweenProfileAndDiff() { From 7a29b65b80602761cd7ee2303e985caa0dc211b1 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 12:21:57 -0700 Subject: [PATCH 25/97] - --- .../devtools_app/lib/src/shared/offline_data.dart | 7 +++++++ .../lib/src/shared/primitives/simple_items.dart | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index 8d0fa5da8a4..c2d33531998 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -8,10 +8,17 @@ import 'package:devtools_app_shared/service.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; +import '../../devtools_app.dart'; import 'config_specific/import_export/import_export.dart'; import 'globals.dart'; import 'routing.dart'; +DevToolsMode get devToolsMode { + return offlineDataController.showingOfflineData.value + ? DevToolsMode.offlineData + : ; +} + /// Controller that manages offline mode for DevTools. /// /// This class will be instantiated once and set as a global [offlineDataController] diff --git a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart index 77ec042ce90..029bb68e10e 100644 --- a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart @@ -57,3 +57,14 @@ enum DocLinks { return '$url#$hash'; } } + +enum DevToolsMode { + /// No connection to app and no data from a previous session. + disconnected, + + /// Interacting with a connected application. + connected, + + /// Showing data saved from a previous session. + offlineData, +} From 4ebae9e4fbd366cdd1b2266a8edd6a43ab17ce1c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 12:27:43 -0700 Subject: [PATCH 26/97] Update offline_data.dart --- packages/devtools_app/lib/src/shared/offline_data.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index c2d33531998..c46ac065b0f 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -10,13 +10,14 @@ import 'package:flutter/foundation.dart'; import '../../devtools_app.dart'; import 'config_specific/import_export/import_export.dart'; -import 'globals.dart'; -import 'routing.dart'; +/// Current mode of DevTools. DevToolsMode get devToolsMode { return offlineDataController.showingOfflineData.value ? DevToolsMode.offlineData - : ; + : serviceConnection.serviceManager.hasConnection + ? DevToolsMode.connected + : DevToolsMode.disconnected; } /// Controller that manages offline mode for DevTools. From 07717899a826dae51c4657a7679c6fb5cebf0058 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 12:33:17 -0700 Subject: [PATCH 27/97] - --- packages/devtools_app/lib/src/shared/globals.dart | 10 ++++++++++ packages/devtools_app/lib/src/shared/offline_data.dart | 9 --------- packages/devtools_app/lib/src/shared/screen.dart | 2 ++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/devtools_app/lib/src/shared/globals.dart b/packages/devtools_app/lib/src/shared/globals.dart index 8bbfd3aec4e..276da992f15 100644 --- a/packages/devtools_app/lib/src/shared/globals.dart +++ b/packages/devtools_app/lib/src/shared/globals.dart @@ -17,6 +17,7 @@ import 'framework_controller.dart'; import 'offline_data.dart'; import 'preferences/preferences.dart'; import 'primitives/message_bus.dart'; +import 'primitives/simple_items.dart'; import 'primitives/storage.dart'; import 'scripts/script_manager.dart'; import 'survey.dart'; @@ -87,3 +88,12 @@ void setStagerMode() { _stagerMode = true; } } + +/// Current mode of DevTools. +DevToolsMode get devToolsMode { + return offlineDataController.showingOfflineData.value + ? DevToolsMode.offlineData + : serviceConnection.serviceManager.hasConnection + ? DevToolsMode.connected + : DevToolsMode.disconnected; +} diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index c46ac065b0f..dd8e9b5f8c3 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -11,15 +11,6 @@ import 'package:flutter/foundation.dart'; import '../../devtools_app.dart'; import 'config_specific/import_export/import_export.dart'; -/// Current mode of DevTools. -DevToolsMode get devToolsMode { - return offlineDataController.showingOfflineData.value - ? DevToolsMode.offlineData - : serviceConnection.serviceManager.hasConnection - ? DevToolsMode.connected - : DevToolsMode.disconnected; -} - /// Controller that manages offline mode for DevTools. /// /// This class will be instantiated once and set as a global [offlineDataController] diff --git a/packages/devtools_app/lib/src/shared/screen.dart b/packages/devtools_app/lib/src/shared/screen.dart index cfee9c6789b..b4f406ba4ce 100644 --- a/packages/devtools_app/lib/src/shared/screen.dart +++ b/packages/devtools_app/lib/src/shared/screen.dart @@ -154,6 +154,8 @@ enum ScreenMetaData { /// * connected /// * not-connected /// +/// See [devToolsMode]. +/// /// A screen may support any combination of modes. /// /// For offline-data and connected modes: From cf4b3412773a16fe80c813e6cd8b5b63f2faeff9 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 12:37:07 -0700 Subject: [PATCH 28/97] Update offline_data.dart --- packages/devtools_app/lib/src/shared/offline_data.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/offline_data.dart b/packages/devtools_app/lib/src/shared/offline_data.dart index dd8e9b5f8c3..8d0fa5da8a4 100644 --- a/packages/devtools_app/lib/src/shared/offline_data.dart +++ b/packages/devtools_app/lib/src/shared/offline_data.dart @@ -8,8 +8,9 @@ import 'package:devtools_app_shared/service.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import '../../devtools_app.dart'; import 'config_specific/import_export/import_export.dart'; +import 'globals.dart'; +import 'routing.dart'; /// Controller that manages offline mode for DevTools. /// From ba0e76d6e3ba8e5acc52f1be86c47c33c9a2f2d0 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 13:44:09 -0700 Subject: [PATCH 29/97] Update simple_items.dart --- .../devtools_app/lib/src/shared/primitives/simple_items.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart index 029bb68e10e..4f39d2146d3 100644 --- a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart @@ -65,6 +65,6 @@ enum DevToolsMode { /// Interacting with a connected application. connected, - /// Showing data saved from a previous session. + /// Showing data saved from a previous session and ignoring connection status. offlineData, } From 2ceab208559092b7b3b37d243fad4c721d7eaae4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 13:46:47 -0700 Subject: [PATCH 30/97] Update simple_items.dart --- .../devtools_app/lib/src/shared/primitives/simple_items.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart index 4f39d2146d3..61846086f51 100644 --- a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart @@ -59,7 +59,7 @@ enum DocLinks { } enum DevToolsMode { - /// No connection to app and no data from a previous session. + /// Not interacting with app or data from a previous session. disconnected, /// Interacting with a connected application. From b23079220689db5d23ba189aacaaa3620b36da4f Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 13:54:32 -0700 Subject: [PATCH 31/97] Update memory_controller.dart --- .../src/screens/memory/framework/memory_controller.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 7158dae9351..148a02c1f46 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -5,8 +5,10 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; +import '../../../shared/globals.dart'; import '../../../shared/memory/class_name.dart'; import '../../../shared/memory/heap_graph_loader.dart'; +import '../../../shared/primitives/simple_items.dart'; import '../panes/chart/controller/chart_pane_controller.dart'; import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; @@ -32,6 +34,11 @@ class MemoryController extends DisposableController shareClassFilterBetweenProfileAndDiff(); } + /// DevTools mode at the time of creation of the controller. + /// + /// DevTools will recreate controller when the mode changes. + final DevToolsMode _mode = devToolsMode; + /// Index of the selected feature tab. /// /// This value is used to set the initial tab selection of the From f64f82671ca6692724668a5c0b827a4b772f90c5 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 15:08:16 -0700 Subject: [PATCH 32/97] Update memory_controller.dart --- .../memory/framework/memory_controller.dart | 119 ++++++++++-------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 5b56a4bc1aa..47c79ccf40b 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -16,11 +16,28 @@ import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; import '../panes/profile/profile_pane_controller.dart'; import '../panes/tracing/tracing_pane_controller.dart'; -import '../shared/primitives/simple_elements.dart'; import 'offline_data/offline_data.dart'; -/// This class contains the business logic for memory screen, for a connected -/// application. +enum DevToolsMode { + /// Not interacting with app or data from a previous session. + disconnected, + + /// Interacting with a connected application. + connected, + + /// Showing data saved from a previous session and ignoring connection status. + offlineData, +} + +DevToolsMode get devToolsMode { + return offlineDataController.showingOfflineData.value + ? DevToolsMode.offlineData + : serviceConnection.serviceManager.hasConnection + ? DevToolsMode.connected + : DevToolsMode.disconnected; +} + +/// This class contains the business logic for memory screen. /// /// This class must not have direct dependencies on web-only libraries. This /// allows tests of the complicated logic in this class to run on the VM. @@ -31,19 +48,16 @@ class MemoryController extends DisposableController AutoDisposeControllerMixin, OfflineScreenControllerMixin { MemoryController({ - @visibleForTesting DiffPaneController? diffPaneController, - @visibleForTesting ProfilePaneController? profilePaneController, + @visibleForTesting DiffPaneController? connectedDiff, + @visibleForTesting ProfilePaneController? connectedProfile, }) { - unawaited(_init(diffPaneController, profilePaneController)); + unawaited(_init(connectedDiff, connectedProfile)); } + bool _dataInitialized = false; ValueNotifier isInitialized = ValueNotifier(false); - /// Mode of memory screen. - /// - /// Is detected at the time of initialization - /// and does not change in lifetime of the controller. - late final MemoryScreenMode mode; + final DevToolsMode _mode = devToolsMode; /// Index of the selected feature tab. /// @@ -73,62 +87,66 @@ class MemoryController extends DisposableController profile.dispose(); } - bool get _devToolsIsShowingOfflineData => - offlineDataController.showingOfflineData.value; - Future _init( - @visibleForTesting DiffPaneController? diffPaneController, - @visibleForTesting ProfilePaneController? profilePaneController, + @visibleForTesting DiffPaneController? connectedDiff, + @visibleForTesting ProfilePaneController? connectedProfile, ) async { - if (_devToolsIsShowingOfflineData) { - assert(diffPaneController == null && profilePaneController == null); - await _maybeInitOfflineDataMode(); - if (!isInitialized.value) await _initDisconnectedMode(); - assert(isInitialized.value); - return; + assert(!isInitialized.value); + switch (_mode) { + case DevToolsMode.disconnected: + throw StateError('Memory screen does not support disconnected mode.'); + case DevToolsMode.connected: + _initializeData( + diffPaneController: connectedDiff, + profilePaneController: connectedProfile, + ); + _connectToApp(); + case DevToolsMode.offlineData: + assert(connectedDiff == null && connectedProfile == null); + await maybeLoadOfflineData( + PerformanceScreen.id, + createData: (json) => OfflineMemoryData.parse(json), + shouldLoad: (data) => !data.isEmpty, + ); + if (!_dataInitialized) _initializeData(); } - await _initConnectedMode(diffPaneController, profilePaneController); - assert(isInitialized.value); - } - - Future _maybeInitOfflineDataMode() async { - assert(_devToolsIsShowingOfflineData); assert(!isInitialized.value); - // Triggers [processOfflineData], that initializes all the controllers. - await maybeLoadOfflineData( - PerformanceScreen.id, - createData: (json) => OfflineMemoryData.parse(json), - shouldLoad: (data) => !data.isEmpty, - ); + isInitialized.value = true; } - Future _initConnectedMode( + void _initializeData({ + OfflineMemoryData? offlineData, @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, - ) async { - assert(!_devToolsIsShowingOfflineData); + }) { assert(!isInitialized.value); - - chart = MemoryChartPaneController(); + assert(!_dataInitialized); + chart = offlineData?.chart ?? MemoryChartPaneController(); diff = diffPaneController ?? + offlineData?.diff ?? DiffPaneController( loader: HeapGraphLoaderRuntime(chart.memoryTimeline), ); - profile = profilePaneController ?? ProfilePaneController(); - + profile = profilePaneController ?? + offlineData?.profile ?? + ProfilePaneController(); control = MemoryControlPaneController( chart.memoryTimeline, exportData: exportData, ); tracing = TracingPaneController(); + selectedFeatureTabIndex = + offlineData?.selectedTab ?? selectedFeatureTabIndex; + + if (offlineData != null) profile.setFilter(offlineData.filter); _shareClassFilterBetweenProfileAndDiff(); - isInitialized.value = true; + + _dataInitialized = true; } - Future _initDisconnectedMode() async { - assert(!_devToolsIsShowingOfflineData); - assert(!isInitialized.value); + void _connectToApp() { + assert(_dataInitialized); } @override @@ -145,15 +163,8 @@ class MemoryController extends DisposableController @override FutureOr processOfflineData(OfflineMemoryData offlineData) { - assert(offlineDataController.showingOfflineData.value); - assert(!isInitialized.value); - diff = offlineData.diff; - profile = offlineData.profile; - chart = offlineData.chart; - selectedFeatureTabIndex = offlineData.selectedTab; - profile.setFilter(offlineData.filter); - diff.derived.applyFilter(offlineData.filter); - isInitialized.value = true; + assert(!_dataInitialized); + _initializeData(offlineData: offlineData); } void _shareClassFilterBetweenProfileAndDiff() { From f1e7e5ece71404a577c8fa52c848cd8cf25e12a7 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 16:58:56 -0700 Subject: [PATCH 33/97] - --- .../memory/framework/memory_controller.dart | 34 +++++-------------- .../profile/profile_pane_controller.dart | 10 ++++-- .../lib/src/screens/memory/tmp_mode.dart | 20 +++++++++++ 3 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 packages/devtools_app/lib/src/screens/memory/tmp_mode.dart diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 47c79ccf40b..37f5d4678af 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -16,27 +16,9 @@ import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; import '../panes/profile/profile_pane_controller.dart'; import '../panes/tracing/tracing_pane_controller.dart'; +import '../tmp_mode.dart'; import 'offline_data/offline_data.dart'; -enum DevToolsMode { - /// Not interacting with app or data from a previous session. - disconnected, - - /// Interacting with a connected application. - connected, - - /// Showing data saved from a previous session and ignoring connection status. - offlineData, -} - -DevToolsMode get devToolsMode { - return offlineDataController.showingOfflineData.value - ? DevToolsMode.offlineData - : serviceConnection.serviceManager.hasConnection - ? DevToolsMode.connected - : DevToolsMode.disconnected; -} - /// This class contains the business logic for memory screen. /// /// This class must not have direct dependencies on web-only libraries. This @@ -108,8 +90,10 @@ class MemoryController extends DisposableController createData: (json) => OfflineMemoryData.parse(json), shouldLoad: (data) => !data.isEmpty, ); + // If shouldLoad returns true, previous line is noop, so data should be initialized. if (!_dataInitialized) _initializeData(); } + assert(_dataInitialized); assert(!isInitialized.value); isInitialized.value = true; } @@ -121,6 +105,7 @@ class MemoryController extends DisposableController }) { assert(!isInitialized.value); assert(!_dataInitialized); + chart = offlineData?.chart ?? MemoryChartPaneController(); diff = diffPaneController ?? offlineData?.diff ?? @@ -135,18 +120,17 @@ class MemoryController extends DisposableController exportData: exportData, ); tracing = TracingPaneController(); - selectedFeatureTabIndex = offlineData?.selectedTab ?? selectedFeatureTabIndex; - - if (offlineData != null) profile.setFilter(offlineData.filter); + profile.setFilter(offlineData?.filter); _shareClassFilterBetweenProfileAndDiff(); _dataInitialized = true; } - void _connectToApp() { + void _connectToApp() async { assert(_dataInitialized); + await serviceConnection.serviceManager.onServiceAvailable; } @override @@ -168,9 +152,7 @@ class MemoryController extends DisposableController } void _shareClassFilterBetweenProfileAndDiff() { - diff.derived.applyFilter( - profile.classFilter.value, - ); + diff.derived.applyFilter(profile.classFilter.value); profile.classFilter.addListener(() { diff.derived.applyFilter(profile.classFilter.value); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 9cd9bb4a6b4..14b21f1af27 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -11,15 +11,18 @@ import 'package:vm_service/vm_service.dart'; import '../../../../shared/config_specific/import_export/import_export.dart'; import '../../../../shared/globals.dart'; import '../../shared/heap/class_filter.dart'; +import '../../tmp_mode.dart'; import 'model.dart'; class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin { - ProfilePaneController(); + ProfilePaneController(this.mode); + + final DevToolsMode mode; factory ProfilePaneController.parse(Map map) { assert(offlineDataController.showingOfflineData.value); - return ProfilePaneController(); + return ProfilePaneController(DevToolsMode.offlineData); } Map prepareForOffline() { @@ -71,7 +74,8 @@ class ProfilePaneController extends DisposableController _initialized = true; } - void setFilter(ClassFilter filter) { + void setFilter(ClassFilter? filter) { + if (filter == null) return; if (filter == _classFilter.value) return; _classFilter.value = filter; final currentProfile = _currentAllocationProfile.value; diff --git a/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart b/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart new file mode 100644 index 00000000000..27428fa17c0 --- /dev/null +++ b/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart @@ -0,0 +1,20 @@ +import '../../shared/globals.dart'; + +enum DevToolsMode { + /// Not interacting with app or data from a previous session. + disconnected, + + /// Interacting with a connected application. + connected, + + /// Showing data saved from a previous session and ignoring connection status. + offlineData, +} + +DevToolsMode get devToolsMode { + return offlineDataController.showingOfflineData.value + ? DevToolsMode.offlineData + : serviceConnection.serviceManager.hasConnection + ? DevToolsMode.connected + : DevToolsMode.disconnected; +} From 9601724c9a4e335127a3756d15c1d636f83be446 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 17:02:20 -0700 Subject: [PATCH 34/97] - --- .../screens/memory/framework/memory_controller.dart | 3 ++- packages/devtools_app/lib/src/shared/globals.dart | 10 ---------- packages/devtools_app/lib/src/shared/utils.dart | 10 ++++++++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 148a02c1f46..7ecda502402 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -5,10 +5,10 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import '../../../shared/globals.dart'; import '../../../shared/memory/class_name.dart'; import '../../../shared/memory/heap_graph_loader.dart'; import '../../../shared/primitives/simple_items.dart'; +import '../../../shared/utils.dart'; import '../panes/chart/controller/chart_pane_controller.dart'; import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; @@ -37,6 +37,7 @@ class MemoryController extends DisposableController /// DevTools mode at the time of creation of the controller. /// /// DevTools will recreate controller when the mode changes. + // ignore: unused_field, TODO(polina-c): https://github.com/flutter/devtools/issues/6972 final DevToolsMode _mode = devToolsMode; /// Index of the selected feature tab. diff --git a/packages/devtools_app/lib/src/shared/globals.dart b/packages/devtools_app/lib/src/shared/globals.dart index 276da992f15..8bbfd3aec4e 100644 --- a/packages/devtools_app/lib/src/shared/globals.dart +++ b/packages/devtools_app/lib/src/shared/globals.dart @@ -17,7 +17,6 @@ import 'framework_controller.dart'; import 'offline_data.dart'; import 'preferences/preferences.dart'; import 'primitives/message_bus.dart'; -import 'primitives/simple_items.dart'; import 'primitives/storage.dart'; import 'scripts/script_manager.dart'; import 'survey.dart'; @@ -88,12 +87,3 @@ void setStagerMode() { _stagerMode = true; } } - -/// Current mode of DevTools. -DevToolsMode get devToolsMode { - return offlineDataController.showingOfflineData.value - ? DevToolsMode.offlineData - : serviceConnection.serviceManager.hasConnection - ? DevToolsMode.connected - : DevToolsMode.disconnected; -} diff --git a/packages/devtools_app/lib/src/shared/utils.dart b/packages/devtools_app/lib/src/shared/utils.dart index 51c64a2f463..2aebe29d4da 100644 --- a/packages/devtools_app/lib/src/shared/utils.dart +++ b/packages/devtools_app/lib/src/shared/utils.dart @@ -22,6 +22,7 @@ import '../../devtools.dart' as devtools; import 'common_widgets.dart'; import 'connected_app.dart'; import 'globals.dart'; +import 'primitives/simple_items.dart'; final _log = Logger('lib/src/shared/utils'); @@ -274,3 +275,12 @@ class DebounceTimer { _timer.cancel(); } } + +/// Current mode of DevTools. +DevToolsMode get devToolsMode { + return offlineDataController.showingOfflineData.value + ? DevToolsMode.offlineData + : serviceConnection.serviceManager.hasConnection + ? DevToolsMode.connected + : DevToolsMode.disconnected; +} From 8193e9e9cd1057d6cfac9f8c20cf4db7f746de01 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Apr 2024 17:31:27 -0700 Subject: [PATCH 35/97] - --- .../memory/framework/memory_controller.dart | 29 ++++++++----------- .../profile/profile_pane_controller.dart | 19 ++---------- .../test_infra/scenes/memory/default.dart | 4 +-- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 37f5d4678af..d142df3f20d 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -33,13 +33,17 @@ class MemoryController extends DisposableController @visibleForTesting DiffPaneController? connectedDiff, @visibleForTesting ProfilePaneController? connectedProfile, }) { + if (connectedDiff != null && connectedProfile != null) { + _mode = DevToolsMode.connected; + } else { + _mode = devToolsMode; + } unawaited(_init(connectedDiff, connectedProfile)); } - bool _dataInitialized = false; - ValueNotifier isInitialized = ValueNotifier(false); + late final DevToolsMode _mode; - final DevToolsMode _mode = devToolsMode; + ValueNotifier isInitialized = ValueNotifier(false); /// Index of the selected feature tab. /// @@ -82,7 +86,6 @@ class MemoryController extends DisposableController diffPaneController: connectedDiff, profilePaneController: connectedProfile, ); - _connectToApp(); case DevToolsMode.offlineData: assert(connectedDiff == null && connectedProfile == null); await maybeLoadOfflineData( @@ -90,12 +93,10 @@ class MemoryController extends DisposableController createData: (json) => OfflineMemoryData.parse(json), shouldLoad: (data) => !data.isEmpty, ); - // If shouldLoad returns true, previous line is noop, so data should be initialized. - if (!_dataInitialized) _initializeData(); + // If shouldLoad returns false, previous line is noop, so data should be initialized. + if (!isInitialized.value) _initializeData(); } - assert(_dataInitialized); - assert(!isInitialized.value); - isInitialized.value = true; + assert(isInitialized.value); } void _initializeData({ @@ -104,7 +105,6 @@ class MemoryController extends DisposableController @visibleForTesting ProfilePaneController? profilePaneController, }) { assert(!isInitialized.value); - assert(!_dataInitialized); chart = offlineData?.chart ?? MemoryChartPaneController(); diff = diffPaneController ?? @@ -125,12 +125,7 @@ class MemoryController extends DisposableController profile.setFilter(offlineData?.filter); _shareClassFilterBetweenProfileAndDiff(); - _dataInitialized = true; - } - - void _connectToApp() async { - assert(_dataInitialized); - await serviceConnection.serviceManager.onServiceAvailable; + isInitialized.value = true; } @override @@ -147,7 +142,7 @@ class MemoryController extends DisposableController @override FutureOr processOfflineData(OfflineMemoryData offlineData) { - assert(!_dataInitialized); + assert(!isInitialized.value); _initializeData(offlineData: offlineData); } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 14b21f1af27..28eb2dedd70 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -11,23 +11,11 @@ import 'package:vm_service/vm_service.dart'; import '../../../../shared/config_specific/import_export/import_export.dart'; import '../../../../shared/globals.dart'; import '../../shared/heap/class_filter.dart'; -import '../../tmp_mode.dart'; import 'model.dart'; class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin { - ProfilePaneController(this.mode); - - final DevToolsMode mode; - - factory ProfilePaneController.parse(Map map) { - assert(offlineDataController.showingOfflineData.value); - return ProfilePaneController(DevToolsMode.offlineData); - } - - Map prepareForOffline() { - return {}; - } + final _exportController = ExportController(); /// The current profile being displayed. ValueListenable get currentAllocationProfile => @@ -74,8 +62,7 @@ class ProfilePaneController extends DisposableController _initialized = true; } - void setFilter(ClassFilter? filter) { - if (filter == null) return; + void setFilter(ClassFilter filter) { if (filter == _classFilter.value) return; _classFilter.value = filter; final currentProfile = _currentAllocationProfile.value; @@ -177,7 +164,7 @@ class ProfilePaneController extends DisposableController ].join(','), ); } - ExportController().downloadFile( + _exportController.downloadFile( csvBuffer.toString(), type: ExportFileType.csv, ); diff --git a/packages/devtools_app/test/test_infra/scenes/memory/default.dart b/packages/devtools_app/test/test_infra/scenes/memory/default.dart index c1d01543bf5..f7c2064c543 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/default.dart @@ -141,8 +141,8 @@ class MemoryDefaultScene extends Scene { final profileController = ProfilePaneController()..setFilter(showAllFilter); controller = MemoryController( - diffPaneController: diffController, - profilePaneController: profileController, + connectedDiff: diffController, + connectedProfile: profileController, ) ..chart.memoryTimeline.offlineData.clear() ..chart.memoryTimeline.offlineData.addAll(memoryJson.data); From 38bc77a456c72d0e1111fb16c174435a1e3ac187 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 07:36:51 -0700 Subject: [PATCH 36/97] - --- .../src/screens/memory/framework/memory_controller.dart | 4 ++-- .../panes/chart/controller/chart_pane_controller.dart | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index d142df3f20d..84de93e9a1b 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -106,7 +106,7 @@ class MemoryController extends DisposableController }) { assert(!isInitialized.value); - chart = offlineData?.chart ?? MemoryChartPaneController(); + chart = offlineData?.chart ?? MemoryChartPaneController(_mode); diff = diffPaneController ?? offlineData?.diff ?? DiffPaneController( @@ -122,7 +122,7 @@ class MemoryController extends DisposableController tracing = TracingPaneController(); selectedFeatureTabIndex = offlineData?.selectedTab ?? selectedFeatureTabIndex; - profile.setFilter(offlineData?.filter); + if (offlineData != null) profile.setFilter(offlineData.filter); _shareClassFilterBetweenProfileAndDiff(); isInitialized.value = true; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 396bdd563d1..ecb5ceb16ec 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -10,6 +10,7 @@ import 'package:vm_service/vm_service.dart'; import '../../../../../shared/globals.dart'; import '../../../shared/primitives/memory_timeline.dart'; +import '../../../tmp_mode.dart'; import '../data/primitives.dart'; import 'android_chart_controller.dart'; import 'event_chart_controller.dart'; @@ -18,12 +19,14 @@ import 'vm_chart_controller.dart'; class MemoryChartPaneController extends DisposableController with AutoDisposeControllerMixin { - MemoryChartPaneController(); + MemoryChartPaneController(this.mode); factory MemoryChartPaneController.parse(Map map) { - return MemoryChartPaneController(); + return MemoryChartPaneController(DevToolsMode.offlineData); } + DevToolsMode mode; + Map prepareForOffline() { return {}; } From dbf826aec24d6c75de83b7794facfaf1390e116b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 07:45:14 -0700 Subject: [PATCH 37/97] Update profile_pane_controller.dart --- .../memory/panes/profile/profile_pane_controller.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 28eb2dedd70..07a2ff7cb85 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -15,6 +15,16 @@ import 'model.dart'; class ProfilePaneController extends DisposableController with AutoDisposeControllerMixin { + ProfilePaneController(); + + factory ProfilePaneController.parse(Map map) { + return ProfilePaneController(); + } + + Map prepareForOffline() { + return {}; + } + final _exportController = ExportController(); /// The current profile being displayed. From c58ce813b1fb373fe799ddd46d16ee87d710e4e2 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 07:53:01 -0700 Subject: [PATCH 38/97] - --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 ++ .../memory/panes/diff/controller/diff_pane_controller.dart | 2 ++ .../screens/memory/panes/profile/profile_pane_controller.dart | 2 ++ 3 files changed, 6 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index ecb5ceb16ec..59028038a15 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -22,12 +22,14 @@ class MemoryChartPaneController extends DisposableController MemoryChartPaneController(this.mode); factory MemoryChartPaneController.parse(Map map) { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return MemoryChartPaneController(DevToolsMode.offlineData); } DevToolsMode mode; Map prepareForOffline() { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return {}; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart index 26217d9a180..ebded45f8cf 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart @@ -32,10 +32,12 @@ class DiffPaneController extends DisposableController { DiffPaneController({required this.loader}); factory DiffPaneController.parse(Map map) { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return DiffPaneController(loader: null); } Map prepareForOffline() { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return {}; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart index 07a2ff7cb85..71b6abdf5e6 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_pane_controller.dart @@ -18,10 +18,12 @@ class ProfilePaneController extends DisposableController ProfilePaneController(); factory ProfilePaneController.parse(Map map) { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return ProfilePaneController(); } Map prepareForOffline() { + // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return {}; } From 9ad3f28fe172ec9ccc77da5518e6225f80f8b6c4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 07:58:35 -0700 Subject: [PATCH 39/97] - --- .../memory/panes/tracing/class_table.dart | 1 + .../memory/panes/tracing/tracing_data.dart | 242 ++++++++++++++++++ .../tracing/tracing_pane_controller.dart | 236 +---------------- .../memory/panes/tracing/tracing_tree.dart | 3 +- 4 files changed, 249 insertions(+), 233 deletions(-) create mode 100644 packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart index 63dd813a14a..2cc043b467d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart @@ -14,6 +14,7 @@ import '../../../../shared/table/table.dart'; import '../../../../shared/table/table_controller.dart'; import '../../../../shared/table/table_data.dart'; import '../../shared/widgets/shared_memory_widgets.dart'; +import 'tracing_data.dart'; import 'tracing_pane_controller.dart'; /// The default width for columns containing *mostly* numeric data (e.g., diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart new file mode 100644 index 00000000000..ce1742f0294 --- /dev/null +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart @@ -0,0 +1,242 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:devtools_app_shared/utils.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:vm_service/vm_service.dart'; + +import '../../../../shared/globals.dart'; +import '../../../../shared/memory/class_name.dart'; +import '../../../../shared/primitives/utils.dart'; +import '../../../../shared/table/table_data.dart'; +import '../../../profiler/cpu_profile_model.dart'; +import '../../../profiler/cpu_profile_transformer.dart'; + +/// A representation of a class and it's allocation tracing state. +class TracedClass with PinnableListEntry { + TracedClass({ + required this.cls, + }) : traceAllocations = false, + instances = 0, + name = HeapClassName.fromClassRef(cls); + + TracedClass._({ + required this.cls, + required this.instances, + required this.traceAllocations, + }) : name = HeapClassName.fromClassRef(cls); + + TracedClass copyWith({ + ClassRef? cls, + int? instances, + bool? traceAllocations, + }) { + return TracedClass._( + cls: cls ?? this.cls, + instances: instances ?? this.instances, + traceAllocations: traceAllocations ?? this.traceAllocations, + ); + } + + final HeapClassName name; + final ClassRef cls; + final int instances; + final bool traceAllocations; + + @override + bool operator ==(Object other) { + if (other is! TracedClass) return false; + return cls == other.cls && + instances == other.instances && + traceAllocations == other.traceAllocations; + } + + @override + int get hashCode => Object.hash(cls, instances, traceAllocations); + + @override + bool get pinToTop => traceAllocations; + + @override + String toString() => + '${cls.name} instances: $instances trace: $traceAllocations'; +} + +/// Contains allocation tracing state for a single isolate. +/// +/// `AllocationProfileTracingController` is effectively only used to provide +/// consumers the allocation tracing state for the currently selected isolate. +class TracingIsolateState { + TracingIsolateState({required this.isolate}); + + TracingIsolateState.empty() : isolate = IsolateRef(); + + final IsolateRef isolate; + + // Keeps track of which classes have allocation tracing enabling. + final tracedClasses = {}; + final tracedClassesProfiles = {}; + final unfilteredClassList = []; + + /// The current class selection in the [AllocationTracingTable] + final selectedTracedClass = ValueNotifier(null); + + /// The list of classes for the currently selected isolate. + ValueListenable> get filteredClassList => + _filteredClassList; + final _filteredClassList = ListValueNotifier([]); + + String currentFilter = ''; + + /// The allocation profile data for the current class selection in the + /// [AllocationTracingTable]. + CpuProfileData? get selectedTracedClassAllocationData { + return tracedClassesProfiles[selectedTracedClass.value?.cls.id!]; + } + + /// The last time, in microseconds, the table was cleared. This time is based + /// on the VM's internal monotonic clock, which is accessible through + /// `service.getVMTimelineMicros()`. + int _lastClearTimeMicros = 0; + + Future initialize() async { + final classList = await serviceConnection.serviceManager.service! + .getClassList(isolate.id!); + for (final cls in classList.classes!) { + tracedClasses[cls.id!] = TracedClass(cls: cls); + } + _filteredClassList.replaceAll(tracedClasses.values); + unfilteredClassList.addAll(tracedClasses.values); + } + + Future refresh() async { + final profileRequests = >[]; + for (final tracedClass in filteredClassList.value) { + // If allocation tracing is enabled for this class, request an updated + // profile. + if (tracedClass.traceAllocations) { + profileRequests.add(_getAllocationProfileForClass(tracedClass)); + } + } + + // All profile requests need to complete before we can consider the refresh + // completed. + await Future.wait(profileRequests); + } + + void updateClassFilter(String newFilter, {bool force = false}) { + if (newFilter.isEmpty && currentFilter.isEmpty && !force) return; + final updatedFilteredClassList = + (newFilter.caseInsensitiveContains(currentFilter) && !force + ? _filteredClassList.value + : unfilteredClassList) + .where( + (e) => e.cls.name!.caseInsensitiveContains(newFilter), + ) + .map((e) => tracedClasses[e.cls.id!]!) + .toList(); + + _filteredClassList.replaceAll(updatedFilteredClassList); + currentFilter = newFilter; + } + + /// Clears the allocation profiles for the currently traced classes. + Future clear() async { + _lastClearTimeMicros = + (await serviceConnection.serviceManager.service!.getVMTimelineMicros()) + .timestamp!; + // Reset the counts for traced classes. + final updatedTracedClasses = tracedClasses.map((key, value) { + return MapEntry(key, value.copyWith(instances: 0)); + }); + + tracedClasses + ..clear() + ..addAll(updatedTracedClasses); + + // Reset the unfiltered class list with the new `TracedClass` instances. + unfilteredClassList + ..clear() + ..addAll(tracedClasses.values); + updateClassFilter(currentFilter, force: true); + + // Since there's no longer any tracing data, clear the existing profiles. + tracedClassesProfiles.clear(); + } + + /// Enables or disables tracing of allocations of [cls]. + Future setAllocationTracingForClass(ClassRef cls, bool enabled) async { + final service = serviceConnection.serviceManager.service!; + final isolate = + serviceConnection.serviceManager.isolateManager.selectedIsolate.value!; + final tracedClass = tracedClasses[cls.id!]!; + + // Only update if the tracing state has changed for `cls`. + if (tracedClass.traceAllocations != enabled) { + await service.setTraceClassAllocation(isolate.id!, cls.id!, enabled); + final update = tracedClass.copyWith( + traceAllocations: enabled, + ); + _updateClassState(tracedClass, update); + } + } + + void _updateClassState(TracedClass original, TracedClass updated) { + final cls = original.cls; + // Update the currently selected class, if it's still being traced. + if (selectedTracedClass.value?.cls.id == cls.id) { + selectedTracedClass.value = updated; + } + tracedClasses[cls.id!] = updated; + _filteredClassList.replace(original, updated); + } + + Future _getAllocationProfileForClass( + TracedClass tracedClass, + ) async { + if (!tracedClass.traceAllocations) { + throw StateError( + 'Attempted to request an allocation profile for a non-traced class', + ); + } + final service = serviceConnection.serviceManager.service!; + final isolateId = serviceConnection + .serviceManager.isolateManager.selectedIsolate.value!.id!; + final cls = tracedClass.cls; + + // Note: we need to provide `timeExtentMicros` to `getAllocationTraces`, + // otherwise the VM will respond with all samples, not just the samples + // collected after `_lastClearTimeMicros`. We'll just use the maximum + // Javascript integer value (2^53 - 1) to represent "infinity". + // Request the allocation profile for the traced class. + final trace = await service.getAllocationTraces( + isolateId, + classId: cls.id!, + timeOriginMicros: _lastClearTimeMicros, + timeExtentMicros: maxJsInt, + ); + + final profileData = await CpuProfileData.generateFromCpuSamples( + isolateId: isolateId, + cpuSamples: trace, + ); + + // Process the allocation profile into a tree. We can reuse the transformer + // from the CPU Profiler tooling since it also makes use of a `CpuSamples` + // response. + final transformer = CpuProfileTransformer(); + await transformer.processData(profileData, processId: ''); + + // Update the traced class data with the updated profile length. + final updated = tracedClass.copyWith( + instances: profileData.cpuSamples.length, + ); + tracedClasses[cls.id!] = updated; + tracedClassesProfiles[cls.id!] = profileData; + + _updateClassState(tracedClass, updated); + return profileData; + } +} diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart index 85d2c87a8cd..5748e00b642 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart @@ -13,235 +13,7 @@ import '../../../../shared/primitives/utils.dart'; import '../../../../shared/table/table_data.dart'; import '../../../profiler/cpu_profile_model.dart'; import '../../../profiler/cpu_profile_transformer.dart'; - -// TODO(bkonyi): make compatible with ClassHeapDetailStats for serialization / -// deserialization support. -/// A representation of a class and it's allocation tracing state. -class TracedClass with PinnableListEntry { - TracedClass({ - required this.cls, - }) : traceAllocations = false, - instances = 0, - name = HeapClassName.fromClassRef(cls); - - TracedClass._({ - required this.cls, - required this.instances, - required this.traceAllocations, - }) : name = HeapClassName.fromClassRef(cls); - - TracedClass copyWith({ - ClassRef? cls, - int? instances, - bool? traceAllocations, - }) { - return TracedClass._( - cls: cls ?? this.cls, - instances: instances ?? this.instances, - traceAllocations: traceAllocations ?? this.traceAllocations, - ); - } - - final HeapClassName name; - final ClassRef cls; - final int instances; - final bool traceAllocations; - - @override - bool operator ==(Object other) { - if (other is! TracedClass) return false; - return cls == other.cls && - instances == other.instances && - traceAllocations == other.traceAllocations; - } - - @override - int get hashCode => Object.hash(cls, instances, traceAllocations); - - @override - bool get pinToTop => traceAllocations; - - @override - String toString() => - '${cls.name} instances: $instances trace: $traceAllocations'; -} - -/// Contains allocation tracing state for a single isolate. -/// -/// `AllocationProfileTracingController` is effectively only used to provide -/// consumers the allocation tracing state for the currently selected isolate. -class TracingIsolateState { - TracingIsolateState({required this.isolate}); - - TracingIsolateState._empty() : isolate = IsolateRef(); - - final IsolateRef isolate; - - // Keeps track of which classes have allocation tracing enabling. - final tracedClasses = {}; - final tracedClassesProfiles = {}; - final unfilteredClassList = []; - - /// The current class selection in the [AllocationTracingTable] - final selectedTracedClass = ValueNotifier(null); - - /// The list of classes for the currently selected isolate. - ValueListenable> get filteredClassList => - _filteredClassList; - final _filteredClassList = ListValueNotifier([]); - - String _currentFilter = ''; - - /// The allocation profile data for the current class selection in the - /// [AllocationTracingTable]. - CpuProfileData? get selectedTracedClassAllocationData { - return tracedClassesProfiles[selectedTracedClass.value?.cls.id!]; - } - - /// The last time, in microseconds, the table was cleared. This time is based - /// on the VM's internal monotonic clock, which is accessible through - /// `service.getVMTimelineMicros()`. - int _lastClearTimeMicros = 0; - - Future initialize() async { - final classList = await serviceConnection.serviceManager.service! - .getClassList(isolate.id!); - for (final cls in classList.classes!) { - tracedClasses[cls.id!] = TracedClass(cls: cls); - } - _filteredClassList.replaceAll(tracedClasses.values); - unfilteredClassList.addAll(tracedClasses.values); - } - - Future refresh() async { - final profileRequests = >[]; - for (final tracedClass in filteredClassList.value) { - // If allocation tracing is enabled for this class, request an updated - // profile. - if (tracedClass.traceAllocations) { - profileRequests.add(_getAllocationProfileForClass(tracedClass)); - } - } - - // All profile requests need to complete before we can consider the refresh - // completed. - await Future.wait(profileRequests); - } - - void updateClassFilter(String newFilter, {bool force = false}) { - if (newFilter.isEmpty && _currentFilter.isEmpty && !force) return; - final updatedFilteredClassList = - (newFilter.caseInsensitiveContains(_currentFilter) && !force - ? _filteredClassList.value - : unfilteredClassList) - .where( - (e) => e.cls.name!.caseInsensitiveContains(newFilter), - ) - .map((e) => tracedClasses[e.cls.id!]!) - .toList(); - - _filteredClassList.replaceAll(updatedFilteredClassList); - _currentFilter = newFilter; - } - - /// Clears the allocation profiles for the currently traced classes. - Future clear() async { - _lastClearTimeMicros = - (await serviceConnection.serviceManager.service!.getVMTimelineMicros()) - .timestamp!; - // Reset the counts for traced classes. - final updatedTracedClasses = tracedClasses.map((key, value) { - return MapEntry(key, value.copyWith(instances: 0)); - }); - - tracedClasses - ..clear() - ..addAll(updatedTracedClasses); - - // Reset the unfiltered class list with the new `TracedClass` instances. - unfilteredClassList - ..clear() - ..addAll(tracedClasses.values); - updateClassFilter(_currentFilter, force: true); - - // Since there's no longer any tracing data, clear the existing profiles. - tracedClassesProfiles.clear(); - } - - /// Enables or disables tracing of allocations of [cls]. - Future setAllocationTracingForClass(ClassRef cls, bool enabled) async { - final service = serviceConnection.serviceManager.service!; - final isolate = - serviceConnection.serviceManager.isolateManager.selectedIsolate.value!; - final tracedClass = tracedClasses[cls.id!]!; - - // Only update if the tracing state has changed for `cls`. - if (tracedClass.traceAllocations != enabled) { - await service.setTraceClassAllocation(isolate.id!, cls.id!, enabled); - final update = tracedClass.copyWith( - traceAllocations: enabled, - ); - _updateClassState(tracedClass, update); - } - } - - void _updateClassState(TracedClass original, TracedClass updated) { - final cls = original.cls; - // Update the currently selected class, if it's still being traced. - if (selectedTracedClass.value?.cls.id == cls.id) { - selectedTracedClass.value = updated; - } - tracedClasses[cls.id!] = updated; - _filteredClassList.replace(original, updated); - } - - Future _getAllocationProfileForClass( - TracedClass tracedClass, - ) async { - if (!tracedClass.traceAllocations) { - throw StateError( - 'Attempted to request an allocation profile for a non-traced class', - ); - } - final service = serviceConnection.serviceManager.service!; - final isolateId = serviceConnection - .serviceManager.isolateManager.selectedIsolate.value!.id!; - final cls = tracedClass.cls; - - // Note: we need to provide `timeExtentMicros` to `getAllocationTraces`, - // otherwise the VM will respond with all samples, not just the samples - // collected after `_lastClearTimeMicros`. We'll just use the maximum - // Javascript integer value (2^53 - 1) to represent "infinity". - // Request the allocation profile for the traced class. - final trace = await service.getAllocationTraces( - isolateId, - classId: cls.id!, - timeOriginMicros: _lastClearTimeMicros, - timeExtentMicros: maxJsInt, - ); - - final profileData = await CpuProfileData.generateFromCpuSamples( - isolateId: isolateId, - cpuSamples: trace, - ); - - // Process the allocation profile into a tree. We can reuse the transformer - // from the CPU Profiler tooling since it also makes use of a `CpuSamples` - // response. - final transformer = CpuProfileTransformer(); - await transformer.processData(profileData, processId: ''); - - // Update the traced class data with the updated profile length. - final updated = tracedClass.copyWith( - instances: profileData.cpuSamples.length, - ); - tracedClasses[cls.id!] = updated; - tracedClassesProfiles[cls.id!] = profileData; - - _updateClassState(tracedClass, updated); - return profileData; - } -} +import 'tracing_data.dart'; class TracingPaneController extends DisposableController with AutoDisposeControllerMixin { @@ -258,7 +30,7 @@ class TracingPaneController extends DisposableController ValueListenable get stateForIsolate => _stateForIsolateListenable; final _stateForIsolateListenable = ValueNotifier( - TracingIsolateState._empty(), + TracingIsolateState.empty(), ); final _stateForIsolate = {}; @@ -277,7 +49,7 @@ class TracingPaneController extends DisposableController serviceConnection.serviceManager.isolateManager.selectedIsolate.value; if (isolate == null) { - _stateForIsolateListenable.value = TracingIsolateState._empty(); + _stateForIsolateListenable.value = TracingIsolateState.empty(); return; } @@ -292,7 +64,7 @@ class TracingPaneController extends DisposableController _stateForIsolate[isolateId] = state; } // Restore the previously applied filter for the isolate. - textEditingController.text = state._currentFilter; + textEditingController.text = state.currentFilter; _stateForIsolateListenable.value = state; } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart index 286e48f2929..8acabbc8305 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_tree.dart @@ -14,6 +14,7 @@ import '../../../../shared/table/table_data.dart'; import '../../../../shared/ui/tab.dart'; import '../../../profiler/cpu_profile_model.dart'; import '../../../profiler/panes/cpu_profile_columns.dart'; +import 'tracing_data.dart'; import 'tracing_pane_controller.dart'; const double _countColumnWidth = 100; @@ -158,7 +159,7 @@ To trace allocations for a class: 2. Interact with your app to trigger an allocation of the class. 3. Click 'Refresh' above to view the tree of collected stack traces of -constructor calls for the selected class. +constructor calls for the selected class. '''; class _TracingTreeHeader extends StatelessWidget { From ad3cb0851c4b4a23835312600704b311a2b41b71 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 08:01:28 -0700 Subject: [PATCH 40/97] Update DEPENDENCIES.md --- .../lib/src/screens/memory/panes/tracing/DEPENDENCIES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/DEPENDENCIES.md b/packages/devtools_app/lib/src/screens/memory/panes/tracing/DEPENDENCIES.md index 8550176ff11..3a007191187 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/DEPENDENCIES.md +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/DEPENDENCIES.md @@ -5,7 +5,10 @@ Dependencies that create loops (inversions) are marked with `!`. ```mermaid flowchart TD; +class_table.dart-->tracing_data.dart; class_table.dart-->tracing_pane_controller.dart; +tracing_pane_controller.dart-->tracing_data.dart; +tracing_tree.dart-->tracing_data.dart; tracing_tree.dart-->tracing_pane_controller.dart; tracing_view.dart-->class_table.dart; tracing_view.dart-->tracing_pane_controller.dart; From 0da6798b0789ccb4cf19cc329d54845d14827758 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 08:32:53 -0700 Subject: [PATCH 41/97] - --- .../lib/src/screens/memory/panes/tracing/tracing_data.dart | 1 - .../memory/panes/tracing/tracing_pane_controller.dart | 5 ----- 2 files changed, 6 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart index ce1742f0294..a9913b17095 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_data.dart @@ -4,7 +4,6 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import 'package:vm_service/vm_service.dart'; import '../../../../shared/globals.dart'; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart index 5748e00b642..cecad3ccac2 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart @@ -8,11 +8,6 @@ import 'package:flutter/widgets.dart'; import 'package:vm_service/vm_service.dart'; import '../../../../shared/globals.dart'; -import '../../../../shared/memory/class_name.dart'; -import '../../../../shared/primitives/utils.dart'; -import '../../../../shared/table/table_data.dart'; -import '../../../profiler/cpu_profile_model.dart'; -import '../../../profiler/cpu_profile_transformer.dart'; import 'tracing_data.dart'; class TracingPaneController extends DisposableController From d5633af9e8f4c54a2109c0ea45c1cce24f80eea6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 10:29:52 -0700 Subject: [PATCH 42/97] Update chart_controller.dart --- .../devtools_app/lib/src/shared/charts/chart_controller.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/shared/charts/chart_controller.dart b/packages/devtools_app/lib/src/shared/charts/chart_controller.dart index e5cb250fa66..e765cdffa97 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart_controller.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart_controller.dart @@ -41,7 +41,6 @@ class ChartController extends DisposableController this.name, List? sharedLabelTimestamps, }) { - // TODO(terry): Compute dynamically based on X-axis labels text height. bottomPadding = !displayXLabels ? 0.0 : 40.0; if (sharedLabelTimestamps != null) { @@ -430,7 +429,7 @@ class ChartController extends DisposableController double yPositionToYCanvasCoord(double y) => -yPosition(y); Trace trace(int index) { - assert(index < traces.length); + assert(index < traces.length, '$index, ${traces.length}'); return traces[index]; } From cbd931f2ab657a7ec5e8d87f5e88d56d87994232 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 11:15:53 -0700 Subject: [PATCH 43/97] - --- .../devtools_app/test/memory/framework/memory_screen_test.dart | 2 +- .../devtools_app/test/test_infra/scenes/memory/default.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/test/memory/framework/memory_screen_test.dart b/packages/devtools_app/test/memory/framework/memory_screen_test.dart index b263140a751..43832ce5231 100644 --- a/packages/devtools_app/test/memory/framework/memory_screen_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_screen_test.dart @@ -78,9 +78,9 @@ void main() { group('MemoryScreen', () { setUp(() { + setUpServiceManagerForMemory(); screen = MemoryScreen(); controller = MemoryController(); - setUpServiceManagerForMemory(); }); testWidgets('builds its tab', (WidgetTester tester) async { diff --git a/packages/devtools_app/test/test_infra/scenes/memory/default.dart b/packages/devtools_app/test/test_infra/scenes/memory/default.dart index 34084b327d2..2c0b8c7a98a 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/default.dart @@ -127,6 +127,7 @@ class MemoryDefaultScene extends Scene { when(fakeServiceConnection.serviceManager.vm.operatingSystem) .thenReturn('ios'); setGlobal(ServiceConnectionManager, fakeServiceConnection); + setGlobal(OfflineDataController, OfflineDataController()); final showAllFilter = ClassFilter( filterType: ClassFilterType.showAll, From e9098b18b509bc6a35d0156cfe38e472db8c71a0 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:23:04 -0700 Subject: [PATCH 44/97] - --- .../memory/framework/memory_controller.dart | 1 - .../controller/chart_pane_controller.dart | 2 +- .../lib/src/screens/memory/tmp_mode.dart | 20 ------------------- 3 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 packages/devtools_app/lib/src/screens/memory/tmp_mode.dart diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 84de93e9a1b..194499ec470 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -16,7 +16,6 @@ import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; import '../panes/profile/profile_pane_controller.dart'; import '../panes/tracing/tracing_pane_controller.dart'; -import '../tmp_mode.dart'; import 'offline_data/offline_data.dart'; /// This class contains the business logic for memory screen. diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 59028038a15..9cc63755e57 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -9,8 +9,8 @@ import 'package:flutter/foundation.dart'; import 'package:vm_service/vm_service.dart'; import '../../../../../shared/globals.dart'; +import '../../../../../shared/primitives/simple_items.dart'; import '../../../shared/primitives/memory_timeline.dart'; -import '../../../tmp_mode.dart'; import '../data/primitives.dart'; import 'android_chart_controller.dart'; import 'event_chart_controller.dart'; diff --git a/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart b/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart deleted file mode 100644 index 27428fa17c0..00000000000 --- a/packages/devtools_app/lib/src/screens/memory/tmp_mode.dart +++ /dev/null @@ -1,20 +0,0 @@ -import '../../shared/globals.dart'; - -enum DevToolsMode { - /// Not interacting with app or data from a previous session. - disconnected, - - /// Interacting with a connected application. - connected, - - /// Showing data saved from a previous session and ignoring connection status. - offlineData, -} - -DevToolsMode get devToolsMode { - return offlineDataController.showingOfflineData.value - ? DevToolsMode.offlineData - : serviceConnection.serviceManager.hasConnection - ? DevToolsMode.connected - : DevToolsMode.disconnected; -} From 64f1961b61e27d05702becd242697e04556aa0f8 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:26:29 -0700 Subject: [PATCH 45/97] Update chart_pane_controller.dart --- .../chart/controller/chart_pane_controller.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 9cc63755e57..d2d8e43a511 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -113,10 +113,10 @@ class MemoryChartPaneController extends DisposableController return serviceConnection.serviceManager.vm?.operatingSystem == 'android'; } - final StreamController memoryTrackerController = + final StreamController _memoryTrackerController = StreamController.broadcast(); - Stream get onMemory => memoryTrackerController.stream; + Stream get onMemory => _memoryTrackerController.stream; MemoryTracker? memoryTracker; @@ -173,12 +173,12 @@ class MemoryChartPaneController extends DisposableController autoDisposeStreamSubscription( memoryTracker!.onChange.listen((_) { - memoryTrackerController.add(memoryTracker); + _memoryTrackerController.add(memoryTracker); }), ); autoDisposeStreamSubscription( memoryTracker!.onChange.listen((_) { - memoryTrackerController.add(memoryTracker); + _memoryTrackerController.add(memoryTracker); }), ); @@ -186,7 +186,7 @@ class MemoryChartPaneController extends DisposableController // memoryController dispose method. Needed when a HOT RELOAD // will call dispose however, initState doesn't seem // to happen David is working on scaffolding. - memoryTrackerController.stream.listen( + _memoryTrackerController.stream.listen( (_) {}, onDone: () { // Stop polling and reset memoryTracker. @@ -204,7 +204,7 @@ class MemoryChartPaneController extends DisposableController void _handleConnectionStop() { memoryTracker?.stop(); - memoryTrackerController.add(memoryTracker); + _memoryTrackerController.add(memoryTracker); memoryTimeline.reset(); hasStopped = true; @@ -227,7 +227,7 @@ class MemoryChartPaneController extends DisposableController @override void dispose() { super.dispose(); - unawaited(memoryTrackerController.close()); + unawaited(_memoryTrackerController.close()); memoryTracker?.dispose(); _legendVisibleNotifier.dispose(); _displayIntervalNotifier.dispose(); From c4dac544e7e1a4b724aacc71e7ee2a270b218991 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:27:45 -0700 Subject: [PATCH 46/97] Update chart_pane_controller.dart --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index d2d8e43a511..6f785267158 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -46,9 +46,7 @@ class MemoryChartPaneController extends DisposableController ); ValueListenable get isLegendVisible => _legendVisibleNotifier; - final _legendVisibleNotifier = ValueNotifier(true); - bool toggleLegendVisibility() => _legendVisibleNotifier.value = !_legendVisibleNotifier.value; From 10b62cf9398088be6d8243cad4f7fece7734136d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:31:17 -0700 Subject: [PATCH 47/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 6f785267158..531f5073695 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -69,37 +69,28 @@ class MemoryChartPaneController extends DisposableController } ValueListenable get refreshCharts => _refreshCharts; - final _refreshCharts = ValueNotifier(0); /// Default is to display default tick width based on width of chart of the collected /// data in the chart. - final _displayIntervalNotifier = + final _displayInterval = ValueNotifier(ChartInterval.theDefault); set displayInterval(ChartInterval interval) { - _displayIntervalNotifier.value = interval; + _displayInterval.value = interval; } - ChartInterval get displayInterval => _displayIntervalNotifier.value; - - final _paused = ValueNotifier(false); + ChartInterval get displayInterval => _displayInterval.value; ValueListenable get paused => _paused; - - void pauseLiveFeed() { - _paused.value = true; - } - - void resumeLiveFeed() { - _paused.value = false; - } - + final _paused = ValueNotifier(false); + void pauseLiveFeed() => _paused.value = true; + void resumeLiveFeed() => _paused.value = false; bool get isPaused => _paused.value; final isAndroidChartVisible = ValueNotifier(false); - void updateAndroidChartVisibility() { + void _updateAndroidChartVisibility() { final bool isConnectedToAndroidAndAndroidEnabled = _isConnectedDeviceAndroid && preferences.memory.androidCollectionEnabled.value; @@ -114,20 +105,21 @@ class MemoryChartPaneController extends DisposableController final StreamController _memoryTrackerController = StreamController.broadcast(); + @visibleForTesting Stream get onMemory => _memoryTrackerController.stream; - MemoryTracker? memoryTracker; + MemoryTracker? _memoryTracker; - bool get hasStarted => memoryTracker != null; + bool get hasStarted => _memoryTracker != null; bool hasStopped = false; void stopTimeLine() { - memoryTracker?.stop(); + _memoryTracker?.stop(); } void _handleConnectionStart() { - memoryTracker ??= MemoryTracker( + _memoryTracker ??= MemoryTracker( memoryTimeline, isAndroidChartVisible: isAndroidChartVisible, paused: paused, @@ -170,13 +162,13 @@ class MemoryChartPaneController extends DisposableController ); autoDisposeStreamSubscription( - memoryTracker!.onChange.listen((_) { - _memoryTrackerController.add(memoryTracker); + _memoryTracker!.onChange.listen((_) { + _memoryTrackerController.add(_memoryTracker); }), ); autoDisposeStreamSubscription( - memoryTracker!.onChange.listen((_) { - _memoryTrackerController.add(memoryTracker); + _memoryTracker!.onChange.listen((_) { + _memoryTrackerController.add(_memoryTracker); }), ); @@ -188,21 +180,21 @@ class MemoryChartPaneController extends DisposableController (_) {}, onDone: () { // Stop polling and reset memoryTracker. - memoryTracker?.stop(); - memoryTracker = null; + _memoryTracker?.stop(); + _memoryTracker = null; }, ); - updateAndroidChartVisibility(); + _updateAndroidChartVisibility(); addAutoDisposeListener( preferences.memory.androidCollectionEnabled, - updateAndroidChartVisibility, + _updateAndroidChartVisibility, ); } void _handleConnectionStop() { - memoryTracker?.stop(); - _memoryTrackerController.add(memoryTracker); + _memoryTracker?.stop(); + _memoryTrackerController.add(_memoryTracker); memoryTimeline.reset(); hasStopped = true; @@ -226,9 +218,9 @@ class MemoryChartPaneController extends DisposableController void dispose() { super.dispose(); unawaited(_memoryTrackerController.close()); - memoryTracker?.dispose(); + _memoryTracker?.dispose(); _legendVisibleNotifier.dispose(); - _displayIntervalNotifier.dispose(); + _displayInterval.dispose(); _refreshCharts.dispose(); event.dispose(); vm.dispose(); From bd0df00a042498414edad85a22c3b0d66ee48ff8 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:32:48 -0700 Subject: [PATCH 48/97] Update chart_pane_controller.dart --- .../panes/chart/controller/chart_pane_controller.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 531f5073695..cd4a1428535 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -112,11 +112,7 @@ class MemoryChartPaneController extends DisposableController bool get hasStarted => _memoryTracker != null; - bool hasStopped = false; - - void stopTimeLine() { - _memoryTracker?.stop(); - } + void stopTimeLine() => _memoryTracker?.stop(); void _handleConnectionStart() { _memoryTracker ??= MemoryTracker( @@ -197,7 +193,6 @@ class MemoryChartPaneController extends DisposableController _memoryTrackerController.add(_memoryTracker); memoryTimeline.reset(); - hasStopped = true; } void startTimeline() { From b2d8f226f5e28e032beb31efa67ac929cf63177e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:49:44 -0700 Subject: [PATCH 49/97] - --- .../panes/chart/controller/chart_pane_controller.dart | 6 ++---- .../src/screens/memory/panes/chart/widgets/chart_pane.dart | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index cd4a1428535..781f8947985 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -112,8 +112,6 @@ class MemoryChartPaneController extends DisposableController bool get hasStarted => _memoryTracker != null; - void stopTimeLine() => _memoryTracker?.stop(); - void _handleConnectionStart() { _memoryTracker ??= MemoryTracker( memoryTimeline, @@ -188,7 +186,7 @@ class MemoryChartPaneController extends DisposableController ); } - void _handleConnectionStop() { + void _onDisconnect() { _memoryTracker?.stop(); _memoryTrackerController.add(_memoryTracker); @@ -200,7 +198,7 @@ class MemoryChartPaneController extends DisposableController if (serviceConnection.serviceManager.connectedState.value.connected) { _handleConnectionStart(); } else { - _handleConnectionStop(); + _onDisconnect(); } }); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart index 602c5003895..1ecac633511 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart @@ -233,8 +233,7 @@ class _MemoryChartPaneState extends State @override void dispose() { - _hideHover(); // hover will leak if not hide - widget.chart.stopTimeLine(); + _hideHover(); super.dispose(); } From b8c4f35bd017a2838863deebcbb0ff4d00e4fb2c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:53:08 -0700 Subject: [PATCH 50/97] Update memory_controller.dart --- .../lib/src/screens/memory/framework/memory_controller.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 819520c2fef..d3895f342dc 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -11,8 +11,6 @@ import 'package:flutter/widgets.dart'; import '../../../../devtools_app.dart'; import '../../../shared/memory/class_name.dart'; import '../../../shared/memory/heap_graph_loader.dart'; -import '../../../shared/primitives/simple_items.dart'; -import '../../../shared/utils.dart'; import '../panes/chart/controller/chart_pane_controller.dart'; import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; From d2a1254e59dc72c4ace413559816b4ac8e59eb80 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:55:46 -0700 Subject: [PATCH 51/97] Update memory_controller.dart --- .../lib/src/screens/memory/framework/memory_controller.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index d3895f342dc..e166a484d09 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -45,7 +45,6 @@ class MemoryController extends DisposableController /// DevTools mode at the time of creation of the controller. /// /// DevTools will recreate controller when the mode changes. - // ignore: unused_field, TODO(polina-c): https://github.com/flutter/devtools/issues/6972 late final DevToolsMode _mode; /// Index of the selected feature tab. From 8f0010b14cd398b4a361a7fa6b5127e8d4ad80b1 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:57:02 -0700 Subject: [PATCH 52/97] Update chart_pane_controller.dart --- .../panes/chart/controller/chart_pane_controller.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 781f8947985..7b1a02931eb 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -112,7 +112,7 @@ class MemoryChartPaneController extends DisposableController bool get hasStarted => _memoryTracker != null; - void _handleConnectionStart() { + void _onConnect() { _memoryTracker ??= MemoryTracker( memoryTimeline, isAndroidChartVisible: isAndroidChartVisible, @@ -196,14 +196,14 @@ class MemoryChartPaneController extends DisposableController void startTimeline() { addAutoDisposeListener(serviceConnection.serviceManager.connectedState, () { if (serviceConnection.serviceManager.connectedState.value.connected) { - _handleConnectionStart(); + _onConnect(); } else { _onDisconnect(); } }); if (serviceConnection.serviceManager.connectedAppInitialized) { - _handleConnectionStart(); + _onConnect(); } } From 6ee54a29d05edd848e202c238502f1cde2f67911 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 9 Apr 2024 12:57:54 -0700 Subject: [PATCH 53/97] Update chart_pane_controller.dart --- .../memory/panes/chart/controller/chart_pane_controller.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 7b1a02931eb..a2995c203f8 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -86,7 +86,6 @@ class MemoryChartPaneController extends DisposableController final _paused = ValueNotifier(false); void pauseLiveFeed() => _paused.value = true; void resumeLiveFeed() => _paused.value = false; - bool get isPaused => _paused.value; final isAndroidChartVisible = ValueNotifier(false); From 9b2c45a2f2f0f9e75a1356f7daf05260c0e6b06a Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 10 Apr 2024 11:28:43 -0700 Subject: [PATCH 54/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index a2995c203f8..a3782a96dbb 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -17,6 +17,48 @@ import 'event_chart_controller.dart'; import 'memory_tracker.dart'; import 'vm_chart_controller.dart'; +/// States of chart connection. +/// +/// In lifetime of one chart controller the states are changed in the following order: +/// [notStarted] -> [connected] -> [disconnected]. +/// Reconnection does not happen. +enum _ConnectionState { + notStarted, + connected, + disconnected, +} + +/// Manages connection between chart and application. +/// +/// Configures the connection first time when it is needed. +/// Pauses / resumes handling memory events when user pauses / resumes chart. +/// Handles accidental disconnect. +/// It is not chart controller's responsibility to handle reconnection and graceful +/// interaction with user. It just should not fail when connection is lost. +/// +/// When connection is lost, [paused] turns to true. +class _ChartConnectionController extends DisposableController { + _ChartConnectionController(); + + _ConnectionState _state = _ConnectionState.notStarted; + + bool get paused => _paused; + bool _paused = true; + set paused(bool value) { + if (_paused == value) return; + _paused = value; + if (!_paused) _maybeConnect(); + } + + void _maybeConnect() { + if (_state != _ConnectionState.notStarted) return; + + _state = _ConnectionState.connected; + } + + void dispose() {} +} + class MemoryChartPaneController extends DisposableController with AutoDisposeControllerMixin { MemoryChartPaneController(this.mode); @@ -33,6 +75,9 @@ class MemoryChartPaneController extends DisposableController return {}; } + late final _ChartConnectionController? _chartConnection = + mode == DevToolsMode.connected ? _ChartConnectionController() : null; + final MemoryTimeline memoryTimeline = MemoryTimeline(); late final EventChartController event = From d58cc26b08f24d0dd19e05e3e5d79fa5644662d5 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 10 Apr 2024 12:23:29 -0700 Subject: [PATCH 55/97] Update chart_pane_controller.dart --- .../chart/controller/chart_pane_controller.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index a3782a96dbb..782e9527675 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -28,6 +28,8 @@ enum _ConnectionState { disconnected, } +typedef _MemoryEventHandler = void Function(Event); + /// Manages connection between chart and application. /// /// Configures the connection first time when it is needed. @@ -38,20 +40,22 @@ enum _ConnectionState { /// /// When connection is lost, [paused] turns to true. class _ChartConnectionController extends DisposableController { - _ChartConnectionController(); + _ChartConnectionController({required this.onData}); + final _MemoryEventHandler onData; _ConnectionState _state = _ConnectionState.notStarted; bool get paused => _paused; bool _paused = true; - set paused(bool value) { + Future setPaused(bool value) async { if (_paused == value) return; _paused = value; - if (!_paused) _maybeConnect(); + if (!_paused) await _maybeConnect(); } - void _maybeConnect() { + Future _maybeConnect() async { if (_state != _ConnectionState.notStarted) return; + await serviceConnection.serviceManager.onServiceAvailable; _state = _ConnectionState.connected; } From 2aaa8dc38dfc0064127aace26f309300752e2b66 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 10 Apr 2024 17:41:53 -0700 Subject: [PATCH 56/97] Update chart_pane_controller.dart --- .../panes/chart/controller/chart_pane_controller.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 782e9527675..c74065c71db 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -80,7 +80,11 @@ class MemoryChartPaneController extends DisposableController } late final _ChartConnectionController? _chartConnection = - mode == DevToolsMode.connected ? _ChartConnectionController() : null; + mode == DevToolsMode.connected + ? _ChartConnectionController(onData: _onMemoryData) + : null; + + void _onMemoryData(Event data) {} final MemoryTimeline memoryTimeline = MemoryTimeline(); From ef8ce6a4d9c09763514f299956be8fce768b3fa9 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 10 Apr 2024 17:51:00 -0700 Subject: [PATCH 57/97] - --- .../controller/chart_pane_controller.dart | 32 ----------------- .../memory/framework/memory_service_test.dart | 34 ------------------- 2 files changed, 66 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index c72e7925e04..77202e134f3 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -100,11 +100,6 @@ class MemoryChartPaneController extends DisposableController return serviceConnection.serviceManager.vm?.operatingSystem == 'android'; } - final StreamController memoryTrackerController = - StreamController.broadcast(); - - Stream get onMemory => memoryTrackerController.stream; - MemoryTracker? memoryTracker; bool get hasStarted => memoryTracker != null; @@ -158,30 +153,6 @@ class MemoryChartPaneController extends DisposableController ), ); - autoDisposeStreamSubscription( - memoryTracker!.onChange.listen((_) { - memoryTrackerController.add(memoryTracker); - }), - ); - autoDisposeStreamSubscription( - memoryTracker!.onChange.listen((_) { - memoryTrackerController.add(memoryTracker); - }), - ); - - // TODO(terry): Used to detect stream being closed from the - // memoryController dispose method. Needed when a HOT RELOAD - // will call dispose however, initState doesn't seem - // to happen David is working on scaffolding. - memoryTrackerController.stream.listen( - (_) {}, - onDone: () { - // Stop polling and reset memoryTracker. - memoryTracker?.stop(); - memoryTracker = null; - }, - ); - updateAndroidChartVisibility(); addAutoDisposeListener( preferences.memory.androidCollectionEnabled, @@ -191,8 +162,6 @@ class MemoryChartPaneController extends DisposableController void _handleConnectionStop() { memoryTracker?.stop(); - memoryTrackerController.add(memoryTracker); - memoryTimeline.reset(); hasStopped = true; } @@ -214,7 +183,6 @@ class MemoryChartPaneController extends DisposableController @override void dispose() { super.dispose(); - unawaited(memoryTrackerController.close()); memoryTracker?.dispose(); _legendVisibleNotifier.dispose(); _displayIntervalNotifier.dispose(); diff --git a/packages/devtools_app/test/memory/framework/memory_service_test.dart b/packages/devtools_app/test/memory/framework/memory_service_test.dart index 31fadd97066..62a12a62130 100644 --- a/packages/devtools_app/test/memory/framework/memory_service_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_service_test.dart @@ -36,31 +36,6 @@ void main() { memoryController = MemoryController(); memoryController.chart.startTimeline(); }; - - group('MemoryController', () { - tearDownAll(() { - unawaited(env.tearDownEnvironment(force: true)); - }); - - test('heap info', () async { - await env.setupEnvironment(); - - memoryController.chart.onMemory.listen((MemoryTracker? memoryTracker) { - if (!serviceConnection.serviceManager.hasConnection) { - // VM Service connection has stopped - unexpected. - fail('VM Service connection stopped unexpectedly.'); - } else { - validateHeapInfo(memoryController.chart.memoryTimeline); - } - }); - - await collectSamples(); // Collect some data. - - expect(memoryTrackersReceived, equals(defaultSampleSize)); - - await env.tearDownEnvironment(); - }); - }); } } @@ -95,12 +70,3 @@ void validateHeapInfo(MemoryTimeline timeline) { memoryTrackersReceived++; } - -const int defaultSampleSize = 5; - -Future collectSamples([int sampleCount = defaultSampleSize]) async { - // Keep memory profiler running for n samples of heap info from the VM. - for (var trackers = 0; trackers < sampleCount; trackers++) { - await memoryController.chart.onMemory.first; - } -} From c91f7c2e9ac558d7e4e8a046514434f6353656f8 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 10 Apr 2024 17:53:17 -0700 Subject: [PATCH 58/97] - --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 -- .../test/memory/framework/memory_service_test.dart | 5 ----- 2 files changed, 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 77202e134f3..8eb835c9a8c 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; import 'package:vm_service/vm_service.dart'; diff --git a/packages/devtools_app/test/memory/framework/memory_service_test.dart b/packages/devtools_app/test/memory/framework/memory_service_test.dart index 62a12a62130..94357cd10d4 100644 --- a/packages/devtools_app/test/memory/framework/memory_service_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_service_test.dart @@ -2,13 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@TestOn('vm') -import 'dart:async'; - import 'package:devtools_app/src/screens/memory/framework/memory_controller.dart'; -import 'package:devtools_app/src/screens/memory/panes/chart/controller/memory_tracker.dart'; import 'package:devtools_app/src/screens/memory/shared/primitives/memory_timeline.dart'; -import 'package:devtools_app/src/shared/globals.dart'; import 'package:devtools_shared/devtools_shared.dart'; import 'package:flutter_test/flutter_test.dart'; From 6b9510e52d933198edbcc178125c648a39fb9672 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 08:27:34 -0700 Subject: [PATCH 59/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 97 ++++++------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index c74065c71db..20e7adf4cc5 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -59,8 +59,6 @@ class _ChartConnectionController extends DisposableController { _state = _ConnectionState.connected; } - - void dispose() {} } class MemoryChartPaneController extends DisposableController @@ -84,8 +82,6 @@ class MemoryChartPaneController extends DisposableController ? _ChartConnectionController(onData: _onMemoryData) : null; - void _onMemoryData(Event data) {} - final MemoryTimeline memoryTimeline = MemoryTimeline(); late final EventChartController event = @@ -154,12 +150,6 @@ class MemoryChartPaneController extends DisposableController return serviceConnection.serviceManager.vm?.operatingSystem == 'android'; } - final StreamController _memoryTrackerController = - StreamController.broadcast(); - - @visibleForTesting - Stream get onMemory => _memoryTrackerController.stream; - MemoryTracker? _memoryTracker; bool get hasStarted => _memoryTracker != null; @@ -175,60 +165,8 @@ class MemoryChartPaneController extends DisposableController // Note: We do not need to listen to event history here because we do not // have matching historical data about total memory usage. autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onExtensionEvent.listen( - (Event event) { - var extensionEventKind = event.extensionKind; - String? customEventKind; - if (MemoryTimeline.isCustomEvent(event.extensionKind!)) { - extensionEventKind = MemoryTimeline.devToolsExtensionEvent; - customEventKind = - MemoryTimeline.customEventName(event.extensionKind!); - } - final jsonData = event.extensionData!.data.cast(); - // TODO(terry): Display events enabled in a settings page for now only these events. - switch (extensionEventKind) { - case 'Flutter.ImageSizesForFrame': - memoryTimeline.addExtensionEvent( - event.timestamp, - event.extensionKind, - jsonData, - ); - break; - case MemoryTimeline.devToolsExtensionEvent: - memoryTimeline.addExtensionEvent( - event.timestamp, - MemoryTimeline.customDevToolsEvent, - jsonData, - customEventName: customEventKind, - ); - break; - } - }, - ), - ); - - autoDisposeStreamSubscription( - _memoryTracker!.onChange.listen((_) { - _memoryTrackerController.add(_memoryTracker); - }), - ); - autoDisposeStreamSubscription( - _memoryTracker!.onChange.listen((_) { - _memoryTrackerController.add(_memoryTracker); - }), - ); - - // TODO(terry): Used to detect stream being closed from the - // memoryController dispose method. Needed when a HOT RELOAD - // will call dispose however, initState doesn't seem - // to happen David is working on scaffolding. - _memoryTrackerController.stream.listen( - (_) {}, - onDone: () { - // Stop polling and reset memoryTracker. - _memoryTracker?.stop(); - _memoryTracker = null; - }, + serviceConnection.serviceManager.service!.onExtensionEvent + .listen(_onMemoryData), ); _updateAndroidChartVisibility(); @@ -238,10 +176,36 @@ class MemoryChartPaneController extends DisposableController ); } + void _onMemoryData(Event data) { + var extensionEventKind = data.extensionKind; + String? customEventKind; + if (MemoryTimeline.isCustomEvent(data.extensionKind!)) { + extensionEventKind = MemoryTimeline.devToolsExtensionEvent; + customEventKind = MemoryTimeline.customEventName(data.extensionKind!); + } + final jsonData = data.extensionData!.data.cast(); + // TODO(terry): Display events enabled in a settings page for now only these events. + switch (extensionEventKind) { + case 'Flutter.ImageSizesForFrame': + memoryTimeline.addExtensionEvent( + data.timestamp, + data.extensionKind, + jsonData, + ); + break; + case MemoryTimeline.devToolsExtensionEvent: + memoryTimeline.addExtensionEvent( + data.timestamp, + MemoryTimeline.customDevToolsEvent, + jsonData, + customEventName: customEventKind, + ); + break; + } + } + void _onDisconnect() { _memoryTracker?.stop(); - _memoryTrackerController.add(_memoryTracker); - memoryTimeline.reset(); } @@ -262,7 +226,6 @@ class MemoryChartPaneController extends DisposableController @override void dispose() { super.dispose(); - unawaited(_memoryTrackerController.close()); _memoryTracker?.dispose(); _legendVisibleNotifier.dispose(); _displayInterval.dispose(); From a5cfeefe1d5528a3b76f3d0b2add6c429c35bbc2 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 12:47:50 -0700 Subject: [PATCH 60/97] Update chart_pane_controller.dart --- .../chart/controller/chart_pane_controller.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 20e7adf4cc5..261771029fb 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -150,16 +150,16 @@ class MemoryChartPaneController extends DisposableController return serviceConnection.serviceManager.vm?.operatingSystem == 'android'; } - MemoryTracker? _memoryTracker; + late final MemoryTracker _memoryTracker = MemoryTracker( + memoryTimeline, + isAndroidChartVisible: isAndroidChartVisible, + paused: paused, + ); - bool get hasStarted => _memoryTracker != null; + bool get hasStarted => paused.value; void _onConnect() { - _memoryTracker ??= MemoryTracker( - memoryTimeline, - isAndroidChartVisible: isAndroidChartVisible, - paused: paused, - )..start(); + _memoryTracker.start(); // Log Flutter extension events. // Note: We do not need to listen to event history here because we do not From 575497b4fe577657ec683d2c41b0cad995fc3921 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 13:01:03 -0700 Subject: [PATCH 61/97] - --- .../panes/chart/controller/memory_tracker.dart | 13 ++++++++++--- .../memory/shared/primitives/memory_timeline.dart | 9 --------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 7bb71132f2e..3dfff3756ee 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -16,6 +16,12 @@ import '../../../shared/primitives/memory_timeline.dart'; final _log = Logger('memory_protocol'); +enum _ContinuesState { + none, + stop, + next, +} + class MemoryTracker { MemoryTracker( this.timeline, { @@ -26,6 +32,7 @@ class MemoryTracker { final MemoryTimeline timeline; final ValueListenable paused; final ValueNotifier isAndroidChartVisible; + _ContinuesState _monitorContinuesState = _ContinuesState.none; Timer? _pollingTimer; @@ -223,9 +230,9 @@ class MemoryTracker { if (eventSample != null && eventSample.isEventAllocationAccumulator) { if (eventSample.allocationAccumulator!.isStart) { // Stop Continuous events being auto posted - a new start is beginning. - timeline.monitorContinuesState = ContinuesState.stop; + _monitorContinuesState = _ContinuesState.stop; } - } else if (timeline.monitorContinuesState == ContinuesState.next) { + } else if (_monitorContinuesState == _ContinuesState.next) { if (_monitorContinues != null) { _monitorContinues!.cancel(); _monitorContinues = null; @@ -259,7 +266,7 @@ class MemoryTracker { if (eventSample != null && eventSample.isEventAllocationAccumulator && eventSample.allocationAccumulator!.isStart) { - timeline.monitorContinuesState = ContinuesState.next; + _monitorContinuesState = _ContinuesState.next; } } diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart index 02f17c3e7aa..60f1070f14d 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart @@ -9,13 +9,6 @@ import 'package:vm_service/vm_service.dart'; import '../../../../shared/primitives/utils.dart'; -enum ContinuesState { - none, - start, - stop, - next, -} - /// All Raw data received from the VM and offline data loaded from a memory log file. class MemoryTimeline { static const delayMs = 500; @@ -60,8 +53,6 @@ class MemoryTimeline { /// List of events awaiting to be posted to HeapSample. final _eventSamples = []; - ContinuesState monitorContinuesState = ContinuesState.none; - void postEventSample(EventSample event) { /* final lastEvent = _eventSamples.safeLast; From 8d4a249f6d5187709736e3fd8ef0c94e2eed6b3a Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 13:09:14 -0700 Subject: [PATCH 62/97] Update memory_tracker.dart --- .../memory/panes/chart/controller/memory_tracker.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 3dfff3756ee..1e72b2553c1 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -47,9 +47,6 @@ class MemoryTracker { /// Polled engine's RasterCache estimates. RasterCache? rasterCache; - Stream get onChange => _changeController.stream; - final _changeController = StreamController.broadcast(); - StreamSubscription? _gcStreamListener; Timer? _monitorContinues; @@ -258,8 +255,6 @@ class MemoryTracker { timeline.addSample(sample); - _changeController.add(null); - // Signal continues events are to be emitted. These events are hidden // until a reset event then the continuous events between last monitor // start/reset and latest reset are made visible. From fab3a2b346d55e15bc9fe14fc01dd887af833f0e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 13:18:12 -0700 Subject: [PATCH 63/97] Update memory_tracker.dart --- .../panes/chart/controller/memory_tracker.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 1e72b2553c1..9c99fc9a3b9 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -222,7 +222,7 @@ class MemoryTracker { } // Process any memory events? - final eventSample = processEventSample(timeline, time); + final eventSample = _processEventSample(timeline, time); if (eventSample != null && eventSample.isEventAllocationAccumulator) { if (eventSample.allocationAccumulator!.isStart) { @@ -272,10 +272,10 @@ class MemoryTracker { /// (time parameter)). /// /// Returns copy of events to associate with an existing HeapSample tick - /// (contained in the EventSample). See [processEventSample] it computes the + /// (contained in the EventSample). See [_processEventSample] it computes the /// events to aggregate to an existing HeapSample or delay associating those /// events until the next HeapSample (tick) received see [_recalculate]. - EventSample pullClone(MemoryTimeline memoryTimeline, int time) { + EventSample _pullClone(MemoryTimeline memoryTimeline, int time) { final pulledEvent = memoryTimeline.pullEventSample(); final extensionEvents = memoryTimeline.extensionEvents; final eventSample = pulledEvent.clone( @@ -289,7 +289,7 @@ class MemoryTracker { return eventSample; } - EventSample? processEventSample(MemoryTimeline memoryTimeline, int time) { + EventSample? _processEventSample(MemoryTimeline memoryTimeline, int time) { if (memoryTimeline.anyEvents) { final eventTime = memoryTimeline.peekEventTimestamp; final timeDuration = Duration(milliseconds: time); @@ -302,7 +302,7 @@ class MemoryTracker { if (compared < 0) { if ((timeDuration + delay).compareTo(eventDuration) >= 0) { // Currently, events are all UI events so duration < _updateDelay - return pullClone(memoryTimeline, time); + return _pullClone(memoryTimeline, time); } // Throw away event, missed attempt to attach to a HeapSample. final ignoreEvent = memoryTimeline.pullEventSample(); @@ -322,13 +322,13 @@ class MemoryTracker { if ((timeDuration - delay).compareTo(eventDuration) >= 0) { // Able to match event time to a heap sample. We will attach the // EventSample to this HeapSample. - return pullClone(memoryTimeline, time); + return _pullClone(memoryTimeline, time); } // Keep the event, its time hasn't caught up to the HeapSample time yet. return null; } // The almost exact eventSample we have. - return pullClone(memoryTimeline, time); + return _pullClone(memoryTimeline, time); } } From ce0ee739c9aa957bd2e692ad2bdb180f466c9881 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 13:19:56 -0700 Subject: [PATCH 64/97] Update memory_tracker.dart --- .../chart/controller/memory_tracker.dart | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 9c99fc9a3b9..fb1decf8ca7 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -36,13 +36,13 @@ class MemoryTracker { Timer? _pollingTimer; - final isolateHeaps = {}; + final _isolateHeaps = {}; /// Polled VM current RSS. int processRss = 0; /// Polled adb dumpsys meminfo values. - AdbMemoryInfo? adbMemoryInfo; + AdbMemoryInfo? _adbMemoryInfo; /// Polled engine's RasterCache estimates. RasterCache? rasterCache; @@ -104,7 +104,7 @@ class MemoryTracker { // Polls for current Android meminfo using: // > adb shell dumpsys meminfo -d - adbMemoryInfo = serviceConnection.serviceManager.hasConnection && + _adbMemoryInfo = serviceConnection.serviceManager.hasConnection && serviceConnection.serviceManager.vm!.operatingSystem == 'android' && isAndroidChartVisible.value ? await _fetchAdbInfo() @@ -143,17 +143,17 @@ class MemoryTracker { void _update(VM vm, Map isolateMemory) { processRss = vm.json!['_currentRSS']; - isolateHeaps.clear(); + _isolateHeaps.clear(); for (IsolateRef isolateRef in isolateMemory.keys) { - isolateHeaps[isolateRef.id!] = isolateMemory[isolateRef]!; + _isolateHeaps[isolateRef.id!] = isolateMemory[isolateRef]!; } _recalculate(); } void _updateGCEvent(String isolateId, MemoryUsage memoryUsage) { - isolateHeaps[isolateId] = memoryUsage; + _isolateHeaps[isolateId] = memoryUsage; _recalculate(true); } @@ -191,11 +191,11 @@ class MemoryTracker { final keysToRemove = []; - final isolateCount = isolateHeaps.length; - final keys = isolateHeaps.keys.toList(); + final isolateCount = _isolateHeaps.length; + final keys = _isolateHeaps.keys.toList(); for (var index = 0; index < isolateCount; index++) { final isolateId = keys[index]; - var usage = isolateHeaps[isolateId]; + var usage = _isolateHeaps[isolateId]; // Check if the isolate is dead (sentinel), null implies sentinel. final checkIsolateUsage = await _isolateMemoryUsage(isolateId, usage); if (checkIsolateUsage == null && !keysToRemove.contains(isolateId)) { @@ -214,7 +214,7 @@ class MemoryTracker { } // Removes any isolate that is a sentinel. - isolateHeaps.removeWhere((key, value) => keysToRemove.contains(key)); + _isolateHeaps.removeWhere((key, value) => keysToRemove.contains(key)); int time = DateTime.now().millisecondsSinceEpoch; if (timeline.data.isNotEmpty) { @@ -248,7 +248,7 @@ class MemoryTracker { used, external, fromGC, - adbMemoryInfo, + _adbMemoryInfo, eventSample, rasterCache, ); From 3aea57c005bb5ec51eae1e2b7f3bcb63f7a6659a Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 14:20:28 -0700 Subject: [PATCH 65/97] - --- .../controller/chart_pane_controller.dart | 23 +++++++------------ .../chart/widgets/chart_control_pane.dart | 3 ++- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 261771029fb..987cc3f586e 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -32,28 +32,21 @@ typedef _MemoryEventHandler = void Function(Event); /// Manages connection between chart and application. /// -/// Configures the connection first time when it is needed. -/// Pauses / resumes handling memory events when user pauses / resumes chart. -/// Handles accidental disconnect. -/// It is not chart controller's responsibility to handle reconnection and graceful -/// interaction with user. It just should not fail when connection is lost. +/// The connection consists of listeners to events from vm and +/// ongoing requests to vm service for current memory usage. +/// +/// When user pauses the chart, the data is still collected. /// -/// When connection is lost, [paused] turns to true. +/// Handles accidental disconnect. +/// It is not the memory screen's responsibility to handle reconnection and graceful +/// interaction with user. The screen just should not fail when connection is lost. class _ChartConnectionController extends DisposableController { _ChartConnectionController({required this.onData}); final _MemoryEventHandler onData; _ConnectionState _state = _ConnectionState.notStarted; - bool get paused => _paused; - bool _paused = true; - Future setPaused(bool value) async { - if (_paused == value) return; - _paused = value; - if (!_paused) await _maybeConnect(); - } - - Future _maybeConnect() async { + Future maybeConnect() async { if (_state != _ConnectionState.notStarted) return; await serviceConnection.serviceManager.onServiceAvailable; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart index aac699fbf45..47e9e3d54a4 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart @@ -24,7 +24,8 @@ class ChartControlPane extends StatefulWidget { @visibleForTesting class ChartPaneTooltips { - static const String pauseTooltip = 'Pause the chart'; + static const String pauseTooltip = + 'Pause the chart. Data will be still collected and shown when you resume.'; static const String resumeTooltip = 'Resume the chart'; } From 815c66e5869dace59ae2326f5669dd081d1439ff Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 14:56:43 -0700 Subject: [PATCH 66/97] - --- .../controller/chart_pane_controller.dart | 47 +++++++------------ .../chart/widgets/chart_control_pane.dart | 4 +- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 987cc3f586e..94ced83effb 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -17,40 +17,23 @@ import 'event_chart_controller.dart'; import 'memory_tracker.dart'; import 'vm_chart_controller.dart'; -/// States of chart connection. -/// -/// In lifetime of one chart controller the states are changed in the following order: -/// [notStarted] -> [connected] -> [disconnected]. -/// Reconnection does not happen. -enum _ConnectionState { - notStarted, - connected, - disconnected, -} - typedef _MemoryEventHandler = void Function(Event); -/// Manages connection between chart and application. +/// Connection between chart and application. /// /// The connection consists of listeners to events from vm and /// ongoing requests to vm service for current memory usage. /// /// When user pauses the chart, the data is still collected. /// -/// Handles accidental disconnect. -/// It is not the memory screen's responsibility to handle reconnection and graceful -/// interaction with user. The screen just should not fail when connection is lost. +/// Does not fail when accidental disconnect happened. class _ChartConnectionController extends DisposableController { _ChartConnectionController({required this.onData}); final _MemoryEventHandler onData; - _ConnectionState _state = _ConnectionState.notStarted; - Future maybeConnect() async { - if (_state != _ConnectionState.notStarted) return; + Future connect() async { await serviceConnection.serviceManager.onServiceAvailable; - - _state = _ConnectionState.connected; } } @@ -70,10 +53,7 @@ class MemoryChartPaneController extends DisposableController return {}; } - late final _ChartConnectionController? _chartConnection = - mode == DevToolsMode.connected - ? _ChartConnectionController(onData: _onMemoryData) - : null; + _ChartConnectionController? _chartConnection; final MemoryTimeline memoryTimeline = MemoryTimeline(); @@ -125,9 +105,17 @@ class MemoryChartPaneController extends DisposableController ChartInterval get displayInterval => _displayInterval.value; ValueListenable get paused => _paused; - final _paused = ValueNotifier(false); - void pauseLiveFeed() => _paused.value = true; - void resumeLiveFeed() => _paused.value = false; + final _paused = ValueNotifier(true); + void pause() => _paused.value = true; + Future resume() async { + if (!_paused.value) return; + if (mode != DevToolsMode.connected) throw StateError('Not connected.'); + if (_chartConnection == null) { + _chartConnection = _ChartConnectionController(onData: _onMemoryData); + await _chartConnection!.connect(); + } + _paused.value = false; + } final isAndroidChartVisible = ValueNotifier(false); @@ -198,7 +186,7 @@ class MemoryChartPaneController extends DisposableController } void _onDisconnect() { - _memoryTracker?.stop(); + _memoryTracker.stop(); memoryTimeline.reset(); } @@ -219,7 +207,7 @@ class MemoryChartPaneController extends DisposableController @override void dispose() { super.dispose(); - _memoryTracker?.dispose(); + _memoryTracker.dispose(); _legendVisibleNotifier.dispose(); _displayInterval.dispose(); _refreshCharts.dispose(); @@ -227,5 +215,6 @@ class MemoryChartPaneController extends DisposableController vm.dispose(); android.dispose(); isAndroidChartVisible.dispose(); + _chartConnection?.dispose(); } } diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart index 47e9e3d54a4..5a6115c5c95 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart @@ -33,12 +33,12 @@ class _ChartControlPaneState extends State with AutoDisposeMixin { void _onPause() { ga.select(gac.memory, gac.pause); - widget.chart.pauseLiveFeed(); + widget.chart.pause(); } void _onResume() { ga.select(gac.memory, gac.resume); - widget.chart.resumeLiveFeed(); + widget.chart.resume(); } void _clearTimeline() { From 694a1df422f3e1a78d0eef4ec45a76a951104914 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 14:58:49 -0700 Subject: [PATCH 67/97] Update chart_pane_controller.dart --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 94ced83effb..515f3f479cc 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -26,7 +26,7 @@ typedef _MemoryEventHandler = void Function(Event); /// /// When user pauses the chart, the data is still collected. /// -/// Does not fail when accidental disconnect happened. +/// Does not fail in case of accidental disconnect. class _ChartConnectionController extends DisposableController { _ChartConnectionController({required this.onData}); From 7999d3cd42afe6b3e045f23df0cdc09c77c1c1d6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 15:05:42 -0700 Subject: [PATCH 68/97] Update chart_control_pane.dart --- .../memory/panes/chart/widgets/chart_control_pane.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart index 5a6115c5c95..b01bf845f7c 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_control_pane.dart @@ -36,9 +36,9 @@ class _ChartControlPaneState extends State widget.chart.pause(); } - void _onResume() { + Future _onResume() async { ga.select(gac.memory, gac.resume); - widget.chart.resume(); + await widget.chart.resume(); } void _clearTimeline() { From a56cc2ef32aa900bed20e8e082958fa3e3ad90d2 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 15:07:25 -0700 Subject: [PATCH 69/97] Update chart_pane_controller.dart --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 515f3f479cc..63165b52c56 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -27,6 +27,8 @@ typedef _MemoryEventHandler = void Function(Event); /// When user pauses the chart, the data is still collected. /// /// Does not fail in case of accidental disconnect. +/// +/// Encapsulates all interactions between chart and vm. class _ChartConnectionController extends DisposableController { _ChartConnectionController({required this.onData}); From f7e3c6412f1d47236486ea8161f2a80285026da4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 15:08:47 -0700 Subject: [PATCH 70/97] Update chart_pane_controller.dart --- .../panes/chart/controller/chart_pane_controller.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 63165b52c56..7a23035c537 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -28,9 +28,9 @@ typedef _MemoryEventHandler = void Function(Event); /// /// Does not fail in case of accidental disconnect. /// -/// Encapsulates all interactions between chart and vm. -class _ChartConnectionController extends DisposableController { - _ChartConnectionController({required this.onData}); +/// All interactions between chart and vm happen through this class. +class _ChartConnection extends DisposableController { + _ChartConnection({required this.onData}); final _MemoryEventHandler onData; @@ -55,7 +55,7 @@ class MemoryChartPaneController extends DisposableController return {}; } - _ChartConnectionController? _chartConnection; + _ChartConnection? _chartConnection; final MemoryTimeline memoryTimeline = MemoryTimeline(); @@ -113,7 +113,7 @@ class MemoryChartPaneController extends DisposableController if (!_paused.value) return; if (mode != DevToolsMode.connected) throw StateError('Not connected.'); if (_chartConnection == null) { - _chartConnection = _ChartConnectionController(onData: _onMemoryData); + _chartConnection = _ChartConnection(onData: _onMemoryData); await _chartConnection!.connect(); } _paused.value = false; From 407fb59a71f1b3dbc14b8d886024cb2aff03aa83 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 16:32:49 -0700 Subject: [PATCH 71/97] - --- .../controller/chart_pane_controller.dart | 27 ++++++++++++++++--- .../chart/controller/memory_tracker.dart | 24 +++++------------ .../memory/panes/chart/data/primitives.dart | 2 ++ .../shared/primitives/memory_timeline.dart | 3 --- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 7a23035c537..d497281fbb2 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -18,6 +18,7 @@ import 'memory_tracker.dart'; import 'vm_chart_controller.dart'; typedef _MemoryEventHandler = void Function(Event); +typedef _PollMemoryHandler = Future Function(); /// Connection between chart and application. /// @@ -28,14 +29,29 @@ typedef _MemoryEventHandler = void Function(Event); /// /// Does not fail in case of accidental disconnect. /// -/// All interactions between chart and vm happen through this class. +/// All interactions between chart and vm are initiated by this class. class _ChartConnection extends DisposableController { - _ChartConnection({required this.onData}); + _ChartConnection({required this.onMemoryData, required this.pollMemory}); - final _MemoryEventHandler onData; + final _MemoryEventHandler onMemoryData; + final _PollMemoryHandler pollMemory; + Timer? _pollingTimer; Future connect() async { await serviceConnection.serviceManager.onServiceAvailable; + await _onPoll(); + } + + Future _onPoll() async { + _pollingTimer = null; + await pollMemory(); + _pollingTimer = Timer(chartUpdateDelay, _onPoll); + } + + @override + void dispose() { + _pollingTimer?.cancel(); + super.dispose(); } } @@ -113,7 +129,10 @@ class MemoryChartPaneController extends DisposableController if (!_paused.value) return; if (mode != DevToolsMode.connected) throw StateError('Not connected.'); if (_chartConnection == null) { - _chartConnection = _ChartConnection(onData: _onMemoryData); + _chartConnection = _ChartConnection( + onMemoryData: _onMemoryData, + pollMemory: _memoryTracker.pollMemory, + ); await _chartConnection!.connect(); } _paused.value = false; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index fb1decf8ca7..77fce839454 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -13,6 +13,7 @@ import 'package:vm_service/vm_service.dart'; import '../../../../../shared/globals.dart'; import '../../../../../shared/utils.dart'; import '../../../shared/primitives/memory_timeline.dart'; +import '../data/primitives.dart'; final _log = Logger('memory_protocol'); @@ -34,8 +35,6 @@ class MemoryTracker { final ValueNotifier isAndroidChartVisible; _ContinuesState _monitorContinuesState = _ContinuesState.none; - Timer? _pollingTimer; - final _isolateHeaps = {}; /// Polled VM current RSS. @@ -57,7 +56,6 @@ class MemoryTracker { } void _updateLiveDataPolling() { - _pollingTimer ??= Timer(MemoryTimeline.updateDelay, _pollMemory); _gcStreamListener ??= serviceConnection.serviceManager.service?.onGCEvent .listen(_handleGCEvent); } @@ -69,10 +67,7 @@ class MemoryTracker { void _cleanListenersAndTimers() { paused.removeListener(_updateLiveDataPolling); - - _pollingTimer?.cancel(); unawaited(_gcStreamListener?.cancel()); - _pollingTimer = null; _gcStreamListener = null; } @@ -89,9 +84,7 @@ class MemoryTracker { _updateGCEvent(event.isolate!.id!, memoryUsage); } - void _pollMemory() async { - _pollingTimer = null; - + Future pollMemory() async { final isolateMemory = {}; for (IsolateRef isolateRef in serviceConnection.serviceManager.isolateManager.isolates.value) { @@ -119,8 +112,6 @@ class MemoryTracker { // TODO(terry): Is there a better way to detect an integration test running? if (vm.json!.containsKey('_FAKE_VM')) return; - - _pollingTimer ??= Timer(MemoryTimeline.updateDelay, _pollMemory); } /// Detect stale isolates (sentineled), may happen after a hot restart. @@ -295,12 +286,11 @@ class MemoryTracker { final timeDuration = Duration(milliseconds: time); final eventDuration = Duration(milliseconds: eventTime); - // If the event is +/- _updateDelay (500 ms) of the current time then - // associate the EventSample with the current HeapSample. - const delay = MemoryTimeline.updateDelay; final compared = timeDuration.compareTo(eventDuration); if (compared < 0) { - if ((timeDuration + delay).compareTo(eventDuration) >= 0) { + // If the event is +/- _updateDelay (500 ms) of the current time then + // associate the EventSample with the current HeapSample. + if ((timeDuration + chartUpdateDelay).compareTo(eventDuration) >= 0) { // Currently, events are all UI events so duration < _updateDelay return _pullClone(memoryTimeline, time); } @@ -317,9 +307,9 @@ class MemoryTracker { if (compared > 0) { final msDiff = time - eventTime; - if (msDiff > MemoryTimeline.delayMs) { + if (msDiff > chartUpdateDelay.inMilliseconds) { // eventSample is in the future. - if ((timeDuration - delay).compareTo(eventDuration) >= 0) { + if ((timeDuration - chartUpdateDelay).compareTo(eventDuration) >= 0) { // Able to match event time to a heap sample. We will attach the // EventSample to this HeapSample. return _pullClone(memoryTimeline, time); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/data/primitives.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/data/primitives.dart index ac1197e7fe8..ba282a9b003 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/data/primitives.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/data/primitives.dart @@ -23,3 +23,5 @@ enum ChartInterval { final String displayName; } + +const Duration chartUpdateDelay = Duration(milliseconds: 500); diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart index 60f1070f14d..fa26c0a8cc8 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart @@ -11,9 +11,6 @@ import '../../../../shared/primitives/utils.dart'; /// All Raw data received from the VM and offline data loaded from a memory log file. class MemoryTimeline { - static const delayMs = 500; - static const Duration updateDelay = Duration(milliseconds: delayMs); - /// This flag will be needed for offline mode implementation. final offline = false; From 74d065641b344a7c6a26eca55570ad14429ee725 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 17:53:10 -0700 Subject: [PATCH 72/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index d497281fbb2..a610b586d4f 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -36,9 +36,12 @@ class _ChartConnection extends DisposableController { final _MemoryEventHandler onMemoryData; final _PollMemoryHandler pollMemory; Timer? _pollingTimer; + bool _connected = false; - Future connect() async { + Future maybeConnect() async { + if (_connected) return; await serviceConnection.serviceManager.onServiceAvailable; + _connected = true; await _onPoll(); } @@ -71,7 +74,13 @@ class MemoryChartPaneController extends DisposableController return {}; } - _ChartConnection? _chartConnection; + late final _ChartConnection? _chartConnection = + (mode == DevToolsMode.connected) + ? _ChartConnection( + onMemoryData: _onMemoryData, + pollMemory: _memoryTracker.pollMemory, + ) + : null; final MemoryTimeline memoryTimeline = MemoryTimeline(); @@ -128,13 +137,7 @@ class MemoryChartPaneController extends DisposableController Future resume() async { if (!_paused.value) return; if (mode != DevToolsMode.connected) throw StateError('Not connected.'); - if (_chartConnection == null) { - _chartConnection = _ChartConnection( - onMemoryData: _onMemoryData, - pollMemory: _memoryTracker.pollMemory, - ); - await _chartConnection!.connect(); - } + await _chartConnection!.maybeConnect(); _paused.value = false; } From e869a703725ded1fd7265413eb5f128bea446857 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 11 Apr 2024 18:27:52 -0700 Subject: [PATCH 73/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index a610b586d4f..9b144bf7eaf 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -38,6 +38,9 @@ class _ChartConnection extends DisposableController { Timer? _pollingTimer; bool _connected = false; + late final isDeviceAndroid = + serviceConnection.serviceManager.vm?.operatingSystem == 'android'; + Future maybeConnect() async { if (_connected) return; await serviceConnection.serviceManager.onServiceAvailable; @@ -60,14 +63,19 @@ class _ChartConnection extends DisposableController { class MemoryChartPaneController extends DisposableController with AutoDisposeControllerMixin { - MemoryChartPaneController(this.mode); + MemoryChartPaneController(this.mode, {this.isDeviceAndroid}) + : assert(mode == DevToolsMode.connected || isDeviceAndroid != null); factory MemoryChartPaneController.parse(Map map) { // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 - return MemoryChartPaneController(DevToolsMode.offlineData); + return MemoryChartPaneController( + DevToolsMode.offlineData, + isDeviceAndroid: false, + ); } DevToolsMode mode; + bool? isDeviceAndroid; Map prepareForOffline() { // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 @@ -144,15 +152,9 @@ class MemoryChartPaneController extends DisposableController final isAndroidChartVisible = ValueNotifier(false); void _updateAndroidChartVisibility() { - final bool isConnectedToAndroidAndAndroidEnabled = - _isConnectedDeviceAndroid && - preferences.memory.androidCollectionEnabled.value; - - isAndroidChartVisible.value = isConnectedToAndroidAndAndroidEnabled; - } - - bool get _isConnectedDeviceAndroid { - return serviceConnection.serviceManager.vm?.operatingSystem == 'android'; + final isAndroid = isDeviceAndroid ?? _chartConnection!.isDeviceAndroid; + isAndroidChartVisible.value = + isAndroid && preferences.memory.androidCollectionEnabled.value; } late final MemoryTracker _memoryTracker = MemoryTracker( From c4993c519782918d3cd24863d21eb8fcc8c5e4e6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 08:24:32 -0700 Subject: [PATCH 74/97] - --- .../memory/framework/memory_controller.dart | 1 + .../chart/controller/chart_pane_controller.dart | 16 +++++++++++++++- .../controller/control_pane_controller.dart | 7 ++++++- .../panes/control/widgets/control_pane.dart | 2 +- .../panes/control/widgets/primary_controls.dart | 6 +++++- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index e166a484d09..0caa3c9f8d0 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -119,6 +119,7 @@ class MemoryController extends DisposableController ProfilePaneController(); control = MemoryControlPaneController( chart.memoryTimeline, + isChartVisible: chart.isChartVisible, exportData: exportData, ); tracing = TracingPaneController(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 9b144bf7eaf..aadccc7a719 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -30,6 +30,7 @@ typedef _PollMemoryHandler = Future Function(); /// Does not fail in case of accidental disconnect. /// /// All interactions between chart and vm are initiated by this class. +/// So, if this class is not instantiated, the interaction does not happen. class _ChartConnection extends DisposableController { _ChartConnection({required this.onMemoryData, required this.pollMemory}); @@ -64,7 +65,12 @@ class _ChartConnection extends DisposableController { class MemoryChartPaneController extends DisposableController with AutoDisposeControllerMixin { MemoryChartPaneController(this.mode, {this.isDeviceAndroid}) - : assert(mode == DevToolsMode.connected || isDeviceAndroid != null); + : assert( + mode == DevToolsMode.connected || isDeviceAndroid != null, + 'If application is not connected, isDeviceAndroid must be provided.', + ) { + unawaited(_init()); + } factory MemoryChartPaneController.parse(Map map) { // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 @@ -77,6 +83,12 @@ class MemoryChartPaneController extends DisposableController DevToolsMode mode; bool? isDeviceAndroid; + Future _init() async { + if (mode == DevToolsMode.connected && isChartVisible.value) { + await resume(); + } + } + Map prepareForOffline() { // TODO(polina-c): implement, https://github.com/flutter/devtools/issues/6972 return {}; @@ -107,6 +119,8 @@ class MemoryChartPaneController extends DisposableController bool toggleLegendVisibility() => _legendVisibleNotifier.value = !_legendVisibleNotifier.value; + ValueNotifier isChartVisible = preferences.memory.showChart; + void resetAll() { event.reset(); vm.reset(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart index 1ded622b30e..410ac52a85d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/controller/control_pane_controller.dart @@ -8,10 +8,15 @@ import '../../../../../shared/globals.dart'; import '../../../shared/primitives/memory_timeline.dart'; class MemoryControlPaneController { - MemoryControlPaneController(this.memoryTimeline, {required this.exportData}); + MemoryControlPaneController( + this.memoryTimeline, { + required this.isChartVisible, + required this.exportData, + }); final MemoryTimeline memoryTimeline; final VoidCallback exportData; + final ValueNotifier isChartVisible; bool get isGcing => _gcing; bool _gcing = false; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart index 386e49350bd..9c959b36e89 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/control_pane.dart @@ -21,7 +21,7 @@ class MemoryControlPane extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const PrimaryControls(), + PrimaryControls(controller: controller), const Spacer(), SecondaryControls(controller: controller), ], diff --git a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/primary_controls.dart b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/primary_controls.dart index ebe7fa6c889..c6fcc053852 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/primary_controls.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/control/widgets/primary_controls.dart @@ -8,21 +8,25 @@ import '../../../../../shared/analytics/constants.dart' as gac; import '../../../../../shared/common_widgets.dart'; import '../../../../../shared/globals.dart'; import '../../../shared/primitives/simple_elements.dart'; +import '../controller/control_pane_controller.dart'; class PrimaryControls extends StatelessWidget { const PrimaryControls({ Key? key, + required this.controller, }) : super(key: key); @visibleForTesting static const memoryChartText = 'Memory chart'; + final MemoryControlPaneController controller; + @override Widget build(BuildContext context) { return VisibilityButton( show: preferences.memory.showChart, gaScreen: gac.memory, - onPressed: (show) => preferences.memory.showChart.value = show, + onPressed: (show) => controller.isChartVisible.value = show, minScreenWidthForTextBeforeScaling: memoryControlsMinVerboseWidth, label: memoryChartText, tooltip: 'Toggle visibility of the Memory usage chart', From e97047d2588db9877f9763e15982b2f5e8d6bb77 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 08:42:14 -0700 Subject: [PATCH 75/97] Update chart_pane_controller.dart --- .../chart/controller/chart_pane_controller.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index aadccc7a719..df4b3c092ef 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -81,12 +81,19 @@ class MemoryChartPaneController extends DisposableController } DevToolsMode mode; - bool? isDeviceAndroid; + + /// Wether device is android, if [mode] is not [DevToolsMode.connected]. + final bool? isDeviceAndroid; Future _init() async { + _updateAndroidChartVisibility(); if (mode == DevToolsMode.connected && isChartVisible.value) { await resume(); } + addAutoDisposeListener( + preferences.memory.androidCollectionEnabled, + _updateAndroidChartVisibility, + ); } Map prepareForOffline() { @@ -191,10 +198,6 @@ class MemoryChartPaneController extends DisposableController ); _updateAndroidChartVisibility(); - addAutoDisposeListener( - preferences.memory.androidCollectionEnabled, - _updateAndroidChartVisibility, - ); } void _onMemoryData(Event data) { From 3b8771580dcd9cd9b724e33dee1c500ab4ff96b1 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 08:46:28 -0700 Subject: [PATCH 76/97] Update chart_pane_controller.dart --- .../chart/controller/chart_pane_controller.dart | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index df4b3c092ef..1f33d96db7b 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -31,7 +31,8 @@ typedef _PollMemoryHandler = Future Function(); /// /// All interactions between chart and vm are initiated by this class. /// So, if this class is not instantiated, the interaction does not happen. -class _ChartConnection extends DisposableController { +class _ChartConnection extends DisposableController + with AutoDisposeControllerMixin { _ChartConnection({required this.onMemoryData, required this.pollMemory}); final _MemoryEventHandler onMemoryData; @@ -45,6 +46,10 @@ class _ChartConnection extends DisposableController { Future maybeConnect() async { if (_connected) return; await serviceConnection.serviceManager.onServiceAvailable; + autoDisposeStreamSubscription( + serviceConnection.serviceManager.service!.onExtensionEvent + .listen(onMemoryData), + ); _connected = true; await _onPoll(); } @@ -189,14 +194,6 @@ class MemoryChartPaneController extends DisposableController void _onConnect() { _memoryTracker.start(); - // Log Flutter extension events. - // Note: We do not need to listen to event history here because we do not - // have matching historical data about total memory usage. - autoDisposeStreamSubscription( - serviceConnection.serviceManager.service!.onExtensionEvent - .listen(_onMemoryData), - ); - _updateAndroidChartVisibility(); } From a897a1f150b12db5cd8a7317e4fa969aa6f84d0b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:07:25 -0700 Subject: [PATCH 77/97] - --- .../controller/chart_pane_controller.dart | 34 +++++-------------- .../panes/chart/widgets/chart_pane.dart | 10 ------ .../memory/framework/memory_service_test.dart | 1 - 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 1f33d96db7b..06343c58059 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -33,10 +33,15 @@ typedef _PollMemoryHandler = Future Function(); /// So, if this class is not instantiated, the interaction does not happen. class _ChartConnection extends DisposableController with AutoDisposeControllerMixin { - _ChartConnection({required this.onMemoryData, required this.pollMemory}); + _ChartConnection( + this._memoryTracker, { + required this.onMemoryData, + required this.pollMemory, + }); final _MemoryEventHandler onMemoryData; final _PollMemoryHandler pollMemory; + final MemoryTracker _memoryTracker; Timer? _pollingTimer; bool _connected = false; @@ -46,6 +51,7 @@ class _ChartConnection extends DisposableController Future maybeConnect() async { if (_connected) return; await serviceConnection.serviceManager.onServiceAvailable; + _memoryTracker.start(); // ????????? autoDisposeStreamSubscription( serviceConnection.serviceManager.service!.onExtensionEvent .listen(onMemoryData), @@ -109,6 +115,7 @@ class MemoryChartPaneController extends DisposableController late final _ChartConnection? _chartConnection = (mode == DevToolsMode.connected) ? _ChartConnection( + _memoryTracker, onMemoryData: _onMemoryData, pollMemory: _memoryTracker.pollMemory, ) @@ -191,12 +198,6 @@ class MemoryChartPaneController extends DisposableController bool get hasStarted => paused.value; - void _onConnect() { - _memoryTracker.start(); - - _updateAndroidChartVisibility(); - } - void _onMemoryData(Event data) { var extensionEventKind = data.extensionKind; String? customEventKind; @@ -225,25 +226,6 @@ class MemoryChartPaneController extends DisposableController } } - void _onDisconnect() { - _memoryTracker.stop(); - memoryTimeline.reset(); - } - - void startTimeline() { - addAutoDisposeListener(serviceConnection.serviceManager.connectedState, () { - if (serviceConnection.serviceManager.connectedState.value.connected) { - _onConnect(); - } else { - _onDisconnect(); - } - }); - - if (serviceConnection.serviceManager.connectedAppInitialized) { - _onConnect(); - } - } - @override void dispose() { super.dispose(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart index 1ecac633511..15972488d1c 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart @@ -146,16 +146,6 @@ class _MemoryChartPaneState extends State addAutoDisposeListener( widget.chart.isAndroidChartVisible, ); - - _updateListeningState(); - } - - void _updateListeningState() async { - await serviceConnection.serviceManager.onServiceAvailable; - - if (!widget.chart.hasStarted) { - widget.chart.startTimeline(); - } } @override diff --git a/packages/devtools_app/test/memory/framework/memory_service_test.dart b/packages/devtools_app/test/memory/framework/memory_service_test.dart index 94357cd10d4..e29a60faef3 100644 --- a/packages/devtools_app/test/memory/framework/memory_service_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_service_test.dart @@ -29,7 +29,6 @@ void main() { env.afterNewSetup = () async { memoryController = MemoryController(); - memoryController.chart.startTimeline(); }; } } From 8b350718279a682af77718b04001f50ea49d5e1a Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:13:41 -0700 Subject: [PATCH 78/97] - --- .../controller/chart_pane_controller.dart | 52 ++----------------- .../chart/controller/memory_tracker.dart | 28 ++++++++++ 2 files changed, 33 insertions(+), 47 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 06343c58059..8f81757c2fd 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import 'package:vm_service/vm_service.dart'; import '../../../../../shared/globals.dart'; import '../../../../../shared/primitives/simple_items.dart'; @@ -17,9 +16,6 @@ import 'event_chart_controller.dart'; import 'memory_tracker.dart'; import 'vm_chart_controller.dart'; -typedef _MemoryEventHandler = void Function(Event); -typedef _PollMemoryHandler = Future Function(); - /// Connection between chart and application. /// /// The connection consists of listeners to events from vm and @@ -33,14 +29,8 @@ typedef _PollMemoryHandler = Future Function(); /// So, if this class is not instantiated, the interaction does not happen. class _ChartConnection extends DisposableController with AutoDisposeControllerMixin { - _ChartConnection( - this._memoryTracker, { - required this.onMemoryData, - required this.pollMemory, - }); - - final _MemoryEventHandler onMemoryData; - final _PollMemoryHandler pollMemory; + _ChartConnection(this._memoryTracker); + final MemoryTracker _memoryTracker; Timer? _pollingTimer; bool _connected = false; @@ -54,7 +44,7 @@ class _ChartConnection extends DisposableController _memoryTracker.start(); // ????????? autoDisposeStreamSubscription( serviceConnection.serviceManager.service!.onExtensionEvent - .listen(onMemoryData), + .listen(_memoryTracker.onMemoryData), ); _connected = true; await _onPoll(); @@ -62,7 +52,7 @@ class _ChartConnection extends DisposableController Future _onPoll() async { _pollingTimer = null; - await pollMemory(); + await _memoryTracker.pollMemory(); _pollingTimer = Timer(chartUpdateDelay, _onPoll); } @@ -114,11 +104,7 @@ class MemoryChartPaneController extends DisposableController late final _ChartConnection? _chartConnection = (mode == DevToolsMode.connected) - ? _ChartConnection( - _memoryTracker, - onMemoryData: _onMemoryData, - pollMemory: _memoryTracker.pollMemory, - ) + ? _ChartConnection(_memoryTracker) : null; final MemoryTimeline memoryTimeline = MemoryTimeline(); @@ -198,34 +184,6 @@ class MemoryChartPaneController extends DisposableController bool get hasStarted => paused.value; - void _onMemoryData(Event data) { - var extensionEventKind = data.extensionKind; - String? customEventKind; - if (MemoryTimeline.isCustomEvent(data.extensionKind!)) { - extensionEventKind = MemoryTimeline.devToolsExtensionEvent; - customEventKind = MemoryTimeline.customEventName(data.extensionKind!); - } - final jsonData = data.extensionData!.data.cast(); - // TODO(terry): Display events enabled in a settings page for now only these events. - switch (extensionEventKind) { - case 'Flutter.ImageSizesForFrame': - memoryTimeline.addExtensionEvent( - data.timestamp, - data.extensionKind, - jsonData, - ); - break; - case MemoryTimeline.devToolsExtensionEvent: - memoryTimeline.addExtensionEvent( - data.timestamp, - MemoryTimeline.customDevToolsEvent, - jsonData, - customEventName: customEventKind, - ); - break; - } - } - @override void dispose() { super.dispose(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index 77fce839454..fabb668443d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -84,6 +84,34 @@ class MemoryTracker { _updateGCEvent(event.isolate!.id!, memoryUsage); } + void onMemoryData(Event data) { + var extensionEventKind = data.extensionKind; + String? customEventKind; + if (MemoryTimeline.isCustomEvent(data.extensionKind!)) { + extensionEventKind = MemoryTimeline.devToolsExtensionEvent; + customEventKind = MemoryTimeline.customEventName(data.extensionKind!); + } + final jsonData = data.extensionData!.data.cast(); + // TODO(terry): Display events enabled in a settings page for now only these events. + switch (extensionEventKind) { + case 'Flutter.ImageSizesForFrame': + timeline.addExtensionEvent( + data.timestamp, + data.extensionKind, + jsonData, + ); + break; + case MemoryTimeline.devToolsExtensionEvent: + timeline.addExtensionEvent( + data.timestamp, + MemoryTimeline.customDevToolsEvent, + jsonData, + customEventName: customEventKind, + ); + break; + } + } + Future pollMemory() async { final isolateMemory = {}; for (IsolateRef isolateRef From f592d2f074621e627813719c381105d4eb4cb7e6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:18:02 -0700 Subject: [PATCH 79/97] - --- .../controller/chart_pane_controller.dart | 8 +++-- .../chart/controller/memory_tracker.dart | 29 +------------------ 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 8f81757c2fd..cbed6c5fb15 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -41,13 +41,16 @@ class _ChartConnection extends DisposableController Future maybeConnect() async { if (_connected) return; await serviceConnection.serviceManager.onServiceAvailable; - _memoryTracker.start(); // ????????? autoDisposeStreamSubscription( serviceConnection.serviceManager.service!.onExtensionEvent .listen(_memoryTracker.onMemoryData), ); - _connected = true; + autoDisposeStreamSubscription( + serviceConnection.serviceManager.service!.onGCEvent + .listen(_memoryTracker.onGCEvent), + ); await _onPoll(); + _connected = true; } Future _onPoll() async { @@ -187,7 +190,6 @@ class MemoryChartPaneController extends DisposableController @override void dispose() { super.dispose(); - _memoryTracker.dispose(); _legendVisibleNotifier.dispose(); _displayInterval.dispose(); _refreshCharts.dispose(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index fabb668443d..c0ad00f01ba 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -46,32 +46,9 @@ class MemoryTracker { /// Polled engine's RasterCache estimates. RasterCache? rasterCache; - StreamSubscription? _gcStreamListener; - Timer? _monitorContinues; - void start() { - _updateLiveDataPolling(); - paused.addListener(_updateLiveDataPolling); - } - - void _updateLiveDataPolling() { - _gcStreamListener ??= serviceConnection.serviceManager.service?.onGCEvent - .listen(_handleGCEvent); - } - - void stop() { - _updateLiveDataPolling(); - _cleanListenersAndTimers(); - } - - void _cleanListenersAndTimers() { - paused.removeListener(_updateLiveDataPolling); - unawaited(_gcStreamListener?.cancel()); - _gcStreamListener = null; - } - - void _handleGCEvent(Event event) { + void onGCEvent(Event event) { final HeapSpace newHeap = HeapSpace.parse(event.json!['new'])!; final HeapSpace oldHeap = HeapSpace.parse(event.json!['old'])!; @@ -357,8 +334,4 @@ class MemoryTracker { return null; } - - void dispose() { - _cleanListenersAndTimers(); - } } From faab0353e8d1672b4c0a37d0314872f3461b08ce Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:23:44 -0700 Subject: [PATCH 80/97] - --- .../memory/panes/chart/controller/chart_pane_controller.dart | 1 - .../screens/memory/panes/chart/controller/memory_tracker.dart | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index cbed6c5fb15..5ab4c5f81ba 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -182,7 +182,6 @@ class MemoryChartPaneController extends DisposableController late final MemoryTracker _memoryTracker = MemoryTracker( memoryTimeline, isAndroidChartVisible: isAndroidChartVisible, - paused: paused, ); bool get hasStarted => paused.value; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index c0ad00f01ba..f79e450c27d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -26,12 +26,10 @@ enum _ContinuesState { class MemoryTracker { MemoryTracker( this.timeline, { - required this.paused, required this.isAndroidChartVisible, }); final MemoryTimeline timeline; - final ValueListenable paused; final ValueNotifier isAndroidChartVisible; _ContinuesState _monitorContinuesState = _ContinuesState.none; From 48a43b779f1b081139f8e0870b132969454376f2 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:23:59 -0700 Subject: [PATCH 81/97] Update chart_pane_controller.dart --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 5ab4c5f81ba..78b727e334f 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -184,8 +184,6 @@ class MemoryChartPaneController extends DisposableController isAndroidChartVisible: isAndroidChartVisible, ); - bool get hasStarted => paused.value; - @override void dispose() { super.dispose(); From 789c2f7757569e5744d19b0517d5f20ae556f028 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:28:05 -0700 Subject: [PATCH 82/97] Update chart_pane_controller.dart --- .../controller/chart_pane_controller.dart | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 78b727e334f..4a0e0797a5d 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -29,9 +29,16 @@ import 'vm_chart_controller.dart'; /// So, if this class is not instantiated, the interaction does not happen. class _ChartConnection extends DisposableController with AutoDisposeControllerMixin { - _ChartConnection(this._memoryTracker); + _ChartConnection(this.timeline, {required this.isAndroidChartVisible}); + + final MemoryTimeline timeline; + final ValueNotifier isAndroidChartVisible; + + late final MemoryTracker _memoryTracker = MemoryTracker( + timeline, + isAndroidChartVisible: isAndroidChartVisible, + ); - final MemoryTracker _memoryTracker; Timer? _pollingTimer; bool _connected = false; @@ -107,7 +114,10 @@ class MemoryChartPaneController extends DisposableController late final _ChartConnection? _chartConnection = (mode == DevToolsMode.connected) - ? _ChartConnection(_memoryTracker) + ? _ChartConnection( + memoryTimeline, + isAndroidChartVisible: isAndroidChartVisible, + ) : null; final MemoryTimeline memoryTimeline = MemoryTimeline(); @@ -179,11 +189,6 @@ class MemoryChartPaneController extends DisposableController isAndroid && preferences.memory.androidCollectionEnabled.value; } - late final MemoryTracker _memoryTracker = MemoryTracker( - memoryTimeline, - isAndroidChartVisible: isAndroidChartVisible, - ); - @override void dispose() { super.dispose(); From 1caa0feb51ffddedfcaa156a75f6b0ee2f367a4b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:29:38 -0700 Subject: [PATCH 83/97] - --- .../memory/panes/chart/controller/chart_pane_controller.dart | 2 +- .../screens/memory/panes/chart/controller/memory_tracker.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 4a0e0797a5d..0920e84d305 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -32,7 +32,7 @@ class _ChartConnection extends DisposableController _ChartConnection(this.timeline, {required this.isAndroidChartVisible}); final MemoryTimeline timeline; - final ValueNotifier isAndroidChartVisible; + final ValueListenable isAndroidChartVisible; late final MemoryTracker _memoryTracker = MemoryTracker( timeline, diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index f79e450c27d..fa9746b5596 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -30,7 +30,7 @@ class MemoryTracker { }); final MemoryTimeline timeline; - final ValueNotifier isAndroidChartVisible; + final ValueListenable isAndroidChartVisible; _ContinuesState _monitorContinuesState = _ContinuesState.none; final _isolateHeaps = {}; From 8ea8e39e3fb20bed5e0421bc23c351a87fbb458c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:33:12 -0700 Subject: [PATCH 84/97] Update memory_tracker.dart --- .../panes/chart/controller/memory_tracker.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart index fa9746b5596..10da1f77ea9 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/memory_tracker.dart @@ -30,13 +30,15 @@ class MemoryTracker { }); final MemoryTimeline timeline; + final ValueListenable isAndroidChartVisible; + _ContinuesState _monitorContinuesState = _ContinuesState.none; final _isolateHeaps = {}; /// Polled VM current RSS. - int processRss = 0; + int _processRss = 0; /// Polled adb dumpsys meminfo values. AdbMemoryInfo? _adbMemoryInfo; @@ -67,7 +69,6 @@ class MemoryTracker { customEventKind = MemoryTimeline.customEventName(data.extensionKind!); } final jsonData = data.extensionData!.data.cast(); - // TODO(terry): Display events enabled in a settings page for now only these events. switch (extensionEventKind) { case 'Flutter.ImageSizesForFrame': timeline.addExtensionEvent( @@ -112,9 +113,6 @@ class MemoryTracker { // Polls for current RSS size. final vm = await serviceConnection.serviceManager.service!.getVM(); _update(vm, isolateMemory); - - // TODO(terry): Is there a better way to detect an integration test running? - if (vm.json!.containsKey('_FAKE_VM')) return; } /// Detect stale isolates (sentineled), may happen after a hot restart. @@ -135,7 +133,7 @@ class MemoryTracker { } void _update(VM vm, Map isolateMemory) { - processRss = vm.json!['_currentRSS']; + _processRss = vm.json!['_currentRSS']; _isolateHeaps.clear(); @@ -236,7 +234,7 @@ class MemoryTracker { final HeapSample sample = HeapSample( time, - processRss, + _processRss, // Displaying capacity dashed line on top of stacked (used + external). capacity + external, used, From 444fa5365b82970beafcc4513fdfbaa44f04ee6c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:34:26 -0700 Subject: [PATCH 85/97] - --- .../panes/chart/controller/chart_pane_controller.dart | 4 ---- .../src/screens/memory/panes/chart/widgets/chart_pane.dart | 6 ------ 2 files changed, 10 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 0920e84d305..6b223642084 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -157,9 +157,6 @@ class MemoryChartPaneController extends DisposableController android.dirty = true; } - ValueListenable get refreshCharts => _refreshCharts; - final _refreshCharts = ValueNotifier(0); - /// Default is to display default tick width based on width of chart of the collected /// data in the chart. final _displayInterval = @@ -194,7 +191,6 @@ class MemoryChartPaneController extends DisposableController super.dispose(); _legendVisibleNotifier.dispose(); _displayInterval.dispose(); - _refreshCharts.dispose(); event.dispose(); vm.dispose(); android.dispose(); diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart index 15972488d1c..977e7dcb9cb 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/widgets/chart_pane.dart @@ -136,12 +136,6 @@ class _MemoryChartPaneState extends State _addTapLocationListener(location, allLocations); } - addAutoDisposeListener(widget.chart.refreshCharts, () { - setState(() { - widget.chart.recomputeChartData(); - }); - }); - // There is no listener passed, so SetState will be invoked. addAutoDisposeListener( widget.chart.isAndroidChartVisible, From e0093a40e2c52fa0bc79a6a28d2750a96416980a Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 09:43:56 -0700 Subject: [PATCH 86/97] - --- packages/devtools_app/lib/src/screens/memory/DEPENDENCIES.md | 1 + .../memory/panes/chart/controller/chart_pane_controller.dart | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/DEPENDENCIES.md b/packages/devtools_app/lib/src/screens/memory/DEPENDENCIES.md index 64f82950ba2..6642a9585e1 100644 --- a/packages/devtools_app/lib/src/screens/memory/DEPENDENCIES.md +++ b/packages/devtools_app/lib/src/screens/memory/DEPENDENCIES.md @@ -6,6 +6,7 @@ Dependencies that create loops (inversions) are marked with `!`. ```mermaid flowchart TD; framework-->panes; +framework-->shared; panes-->shared; ``` diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart index 6b223642084..e74e41d3c89 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/controller/chart_pane_controller.dart @@ -94,6 +94,9 @@ class MemoryChartPaneController extends DisposableController DevToolsMode mode; /// Wether device is android, if [mode] is not [DevToolsMode.connected]. + /// + /// If [mode] is [DevToolsMode.connected], this value should be detected + /// by [_chartConnection]. final bool? isDeviceAndroid; Future _init() async { From 0ec2767d1f7cd90a3e63504d5e44dba3596d9359 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 13:36:19 -0700 Subject: [PATCH 87/97] - --- .../memory/framework/memory_controller.dart | 25 +++++++++++-------- .../screens/memory/framework/screen_body.dart | 13 +++++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 0caa3c9f8d0..fef63de2318 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -8,9 +8,12 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; -import '../../../../devtools_app.dart'; import '../../../shared/memory/class_name.dart'; import '../../../shared/memory/heap_graph_loader.dart'; +import '../../../shared/offline_data.dart'; +import '../../../shared/primitives/simple_items.dart'; +import '../../../shared/screen.dart'; +import '../../../shared/utils.dart'; import '../panes/chart/controller/chart_pane_controller.dart'; import '../panes/control/controller/control_pane_controller.dart'; import '../panes/diff/controller/diff_pane_controller.dart'; @@ -40,7 +43,8 @@ class MemoryController extends DisposableController unawaited(_init(connectedDiff, connectedProfile)); } - ValueNotifier isInitialized = ValueNotifier(false); + Future get initialized => _initialized.future; + final _initialized = Completer(); /// DevTools mode at the time of creation of the controller. /// @@ -79,10 +83,11 @@ class MemoryController extends DisposableController @visibleForTesting DiffPaneController? connectedDiff, @visibleForTesting ProfilePaneController? connectedProfile, ) async { - assert(!isInitialized.value); + assert(!_initialized.isCompleted); switch (_mode) { case DevToolsMode.disconnected: - throw StateError('Memory screen does not support disconnected mode.'); + // TODO: load memory screen in disconnected mode, https://github.com/flutter/devtools/issues/6972 + _initializeData(); case DevToolsMode.connected: _initializeData( diffPaneController: connectedDiff, @@ -91,14 +96,14 @@ class MemoryController extends DisposableController case DevToolsMode.offlineData: assert(connectedDiff == null && connectedProfile == null); await maybeLoadOfflineData( - PerformanceScreen.id, + ScreenMetaData.memory.id, createData: (json) => OfflineMemoryData.parse(json), shouldLoad: (data) => !data.isEmpty, ); // If shouldLoad returns false, previous line is noop, so data should be initialized. - if (!isInitialized.value) _initializeData(); + if (!_initialized.isCompleted) _initializeData(); } - assert(isInitialized.value); + assert(_initialized.isCompleted); } void _initializeData({ @@ -106,7 +111,7 @@ class MemoryController extends DisposableController @visibleForTesting DiffPaneController? diffPaneController, @visibleForTesting ProfilePaneController? profilePaneController, }) { - assert(!isInitialized.value); + assert(!_initialized.isCompleted); chart = offlineData?.chart ?? MemoryChartPaneController(_mode); diff = diffPaneController ?? @@ -128,7 +133,7 @@ class MemoryController extends DisposableController if (offlineData != null) profile.setFilter(offlineData.filter); _shareClassFilterBetweenProfileAndDiff(); - isInitialized.value = true; + _initialized.complete(); } @override @@ -145,7 +150,7 @@ class MemoryController extends DisposableController @override FutureOr processOfflineData(OfflineMemoryData offlineData) { - assert(!isInitialized.value); + assert(!_initialized.isCompleted); _initializeData(offlineData: offlineData); } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart index 24605f528bd..e8683537cd6 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/material.dart'; @@ -31,10 +33,19 @@ class _ConnectedMemoryBodyState extends State final _focusNode = FocusNode(debugLabel: 'memory'); + bool _initialized = false; + @override void initState() { super.initState(); autoDisposeFocusNode(_focusNode); + unawaited(_init()); + } + + Future _init() async { + await memoryController.initialized; + _initialized = true; + setState(() {}); } @override @@ -52,7 +63,7 @@ class _ConnectedMemoryBodyState extends State @override Widget build(BuildContext context) { - if (!memoryController.isInitialized.value) { + if (!_initialized) { return const Center( child: CircularProgressIndicator(), ); From b96eb7620854ad1ca103e04ae7ea890fea42715c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 13:51:04 -0700 Subject: [PATCH 88/97] - --- .../lib/src/screens/memory/framework/memory_controller.dart | 5 ++--- .../screens/memory/framework/offline_data/offline_data.dart | 6 ++---- .../memory/panes/diff/controller/diff_pane_controller.dart | 5 +---- .../lib/src/screens/memory/shared/heap/class_filter.dart | 2 ++ 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index fef63de2318..f782819d4d3 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -98,10 +98,9 @@ class MemoryController extends DisposableController await maybeLoadOfflineData( ScreenMetaData.memory.id, createData: (json) => OfflineMemoryData.parse(json), - shouldLoad: (data) => !data.isEmpty, + shouldLoad: (data) => true, ); - // If shouldLoad returns false, previous line is noop, so data should be initialized. - if (!_initialized.isCompleted) _initializeData(); + assert(_initialized.isCompleted); } assert(_initialized.isCompleted); } diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index 3d36362899a..faf56a807f2 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -21,10 +21,11 @@ class OfflineMemoryData { this.profile, this.chart, this.filter, { - this.isEmpty = false, required this.selectedTab, }); + // TODO: use an extension type for the Json parsing, https://github.com/flutter/devtools/issues/6972 + // https://github.com/flutter/devtools/pull/7572#discussion_r1563102256 factory OfflineMemoryData.parse(Map json) { Map item(String key) => json[key] as Map? ?? {}; @@ -34,12 +35,9 @@ class OfflineMemoryData { MemoryChartPaneController.parse(item(_Json.chartData)), ClassFilter.parse(item(_Json.classFilter)), selectedTab: json[_Json.selectedTab] as int? ?? 0, - isEmpty: json.isEmpty, ); } - final bool isEmpty; - final int selectedTab; final ClassFilter filter; // filter is shared between tabs, so it's here diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart index ebded45f8cf..d46b75856a0 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/controller/diff_pane_controller.dart @@ -53,18 +53,15 @@ class DiffPaneController extends DisposableController { bool get hasSnapshots => core.snapshots.value.length > 1; Future takeSnapshot() async { - final loader = this.loader!; ga.select( gac.memory, gac.MemoryEvent.diffTakeSnapshotControlPane, ); - final item = SnapshotDataItem( displayNumber: _nextDisplayNumber(), defaultName: selectedIsolateName ?? '', ); - - await _addSnapshot(loader, item); + await _addSnapshot(loader!, item); derived._updateValues(); } diff --git a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart index dee0f81331a..9585ae05976 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/heap/class_filter.dart @@ -75,6 +75,8 @@ class ClassFilter { ); } + // TODO: use an extension type for the Json parsing, https://github.com/flutter/devtools/issues/6972 + // https://github.com/flutter/devtools/pull/7572#discussion_r1563130198 Map prepareForOffline() { return { _Json.type: filterType.name, From 324d0d4d9dcaf34019fc818f596ebc7622e567f4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 14:33:28 -0700 Subject: [PATCH 89/97] Update screen_body.dart --- .../screens/memory/framework/screen_body.dart | 58 +++++++++---------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart index e8683537cd6..1b2d857553f 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/material.dart'; @@ -33,19 +31,10 @@ class _ConnectedMemoryBodyState extends State final _focusNode = FocusNode(debugLabel: 'memory'); - bool _initialized = false; - @override void initState() { super.initState(); autoDisposeFocusNode(_focusNode); - unawaited(_init()); - } - - Future _init() async { - await memoryController.initialized; - _initialized = true; - setState(() {}); } @override @@ -63,27 +52,32 @@ class _ConnectedMemoryBodyState extends State @override Widget build(BuildContext context) { - if (!_initialized) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return Column( - key: MemoryChartPane.hoverKey, - children: [ - MemoryControlPane( - controller: controller.control, - ), - const SizedBox(height: intermediateSpacing), - MemoryChartPane( - chart: controller.chart, - keyFocusNode: _focusNode, - ), - Expanded( - child: MemoryTabView(memoryController), - ), - ], + return FutureBuilder( + future: memoryController.initialized, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Column( + key: MemoryChartPane.hoverKey, + children: [ + MemoryControlPane( + controller: controller.control, + ), + const SizedBox(height: intermediateSpacing), + MemoryChartPane( + chart: controller.chart, + keyFocusNode: _focusNode, + ), + Expanded( + child: MemoryTabView(memoryController), + ), + ], + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, ); } } From 245fad1b5a168f379b60ddc83950a012e2fbbd68 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 14:41:28 -0700 Subject: [PATCH 90/97] Update memory_controller.dart --- .../lib/src/screens/memory/framework/memory_controller.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index f782819d4d3..c163c70e596 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -100,6 +100,7 @@ class MemoryController extends DisposableController createData: (json) => OfflineMemoryData.parse(json), shouldLoad: (data) => true, ); + if (!_initialized.isCompleted) _initializeData(); assert(_initialized.isCompleted); } assert(_initialized.isCompleted); From 709f42570f13f57163d4fd0cbb3131a15d044dea Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 16:01:43 -0700 Subject: [PATCH 91/97] Update memory_controller.dart --- .../lib/src/screens/memory/framework/memory_controller.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index c163c70e596..676f59d5a07 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -100,6 +100,8 @@ class MemoryController extends DisposableController createData: (json) => OfflineMemoryData.parse(json), shouldLoad: (data) => true, ); + // [maybeLoadOfflineData] will be a noop if there is no offline data for the memory screen, + // so ensure we still call [_initializedData] if it has not been called. if (!_initialized.isCompleted) _initializeData(); assert(_initialized.isCompleted); } From b4a4166f646c1e0c2d004ef80ddf1e1c8b11cb9d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 12 Apr 2024 17:39:06 -0700 Subject: [PATCH 92/97] Update scene_test_extensions.dart --- .../test_infra/scenes/scene_test_extensions.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart b/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart index 0512d53e9aa..b3b45e8b0ae 100644 --- a/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart +++ b/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart @@ -8,10 +8,12 @@ import 'package:stager/stager.dart'; extension StagerTestExtensions on WidgetTester { Future pumpScene(Scene scene) async { - await pumpWidget( - Builder( - builder: (BuildContext context) => scene.build(context), - ), - ); + await runAsync(() async { + await pumpWidget( + Builder( + builder: (BuildContext context) => scene.build(context), + ), + ); + }); } } From 9b8518b354913995fea4940ffc80ec8db25c395d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 13 Apr 2024 16:05:31 -0700 Subject: [PATCH 93/97] Update memory_screen_test.dart --- .../test/memory/framework/memory_screen_test.dart | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/devtools_app/test/memory/framework/memory_screen_test.dart b/packages/devtools_app/test/memory/framework/memory_screen_test.dart index 43832ce5231..939471886bb 100644 --- a/packages/devtools_app/test/memory/framework/memory_screen_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_screen_test.dart @@ -69,7 +69,8 @@ void main() { ); // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); + await tester + .runAsync(() async => tester.pumpAndSettle(const Duration(seconds: 1))); expect(find.byType(MemoryBody), findsOneWidget); } @@ -101,15 +102,6 @@ void main() { expect(find.text('GC'), findsOneWidget); expect(find.byType(MemoryVMChart), findsOneWidget); - - expect( - controller.chart.memoryTimeline.liveData.isEmpty, - isTrue, - ); - expect( - controller.chart.memoryTimeline.offlineData.isEmpty, - isTrue, - ); }, ); }); From 20ebec2e76cfaf638ff5c03f057116eca9ce3f63 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 13 Apr 2024 16:09:40 -0700 Subject: [PATCH 94/97] - --- .../test/memory/control/settings_dialog_test.dart | 2 +- .../test/memory/diff/widgets/diff_pane_test.dart | 2 +- .../test/memory/framework/memory_controller_test.dart | 2 +- .../test/memory/tracing/tracing_view_test.dart | 2 +- .../test/test_infra/scenes/scene_test_extensions.dart | 8 ++++++++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/test/memory/control/settings_dialog_test.dart b/packages/devtools_app/test/memory/control/settings_dialog_test.dart index 2012880eb9f..ec6dc4e179d 100644 --- a/packages/devtools_app/test/memory/control/settings_dialog_test.dart +++ b/packages/devtools_app/test/memory/control/settings_dialog_test.dart @@ -19,7 +19,7 @@ void main() { late MemoryDefaultScene scene; Future pumpMemoryScreen(WidgetTester tester) async { - await tester.pumpScene(scene); + await tester.pumpSceneAsync(scene); // Delay to ensure the memory profiler has collected data. await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.byType(MemoryBody), findsOneWidget); diff --git a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart index 532955a01de..295996d62e4 100644 --- a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart +++ b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart @@ -15,7 +15,7 @@ import '../../../test_infra/scenes/memory/default.dart'; import '../../../test_infra/scenes/scene_test_extensions.dart'; Future pumpScene(WidgetTester tester, MemoryDefaultScene scene) async { - await tester.pumpScene(scene); + await tester.pumpSceneAsync(scene); // Delay to ensure the memory profiler has collected data. await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.byType(MemoryBody), findsOneWidget); diff --git a/packages/devtools_app/test/memory/framework/memory_controller_test.dart b/packages/devtools_app/test/memory/framework/memory_controller_test.dart index b9d426bd165..3edda6b16be 100644 --- a/packages/devtools_app/test/memory/framework/memory_controller_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_controller_test.dart @@ -25,7 +25,7 @@ final _filter2 = ClassFilter( ); Future pumpScene(WidgetTester tester, MemoryDefaultScene scene) async { - await tester.pumpScene(scene); + await tester.pumpSceneAsync(scene); // Delay to ensure the memory profiler has collected data. await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.byType(MemoryBody), findsOneWidget); diff --git a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart index 52b0483468f..88699704453 100644 --- a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart +++ b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart @@ -59,7 +59,7 @@ void main() { late final CpuSamples allocationTracingProfile; Future pumpScene(WidgetTester tester) async { - await tester.pumpScene(scene); + await tester.pumpSceneAsync(scene); // Delay to ensure the memory profiler has collected data. await tester.pumpAndSettle(const Duration(seconds: 1)); expect(find.byType(MemoryBody), findsOneWidget); diff --git a/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart b/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart index b3b45e8b0ae..0ee0a18fff8 100644 --- a/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart +++ b/packages/devtools_app/test/test_infra/scenes/scene_test_extensions.dart @@ -8,6 +8,14 @@ import 'package:stager/stager.dart'; extension StagerTestExtensions on WidgetTester { Future pumpScene(Scene scene) async { + await pumpWidget( + Builder( + builder: (BuildContext context) => scene.build(context), + ), + ); + } + + Future pumpSceneAsync(Scene scene) async { await runAsync(() async { await pumpWidget( Builder( From 5fc768d493657015c14110c5e426e2694168142e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 13 Apr 2024 16:41:37 -0700 Subject: [PATCH 95/97] - --- .../test/memory/control/settings_dialog_test.dart | 9 +-------- .../test/memory/diff/widgets/diff_pane_test.dart | 5 +---- .../memory/framework/memory_controller_test.dart | 6 ++---- .../allocation_profile_table_view_test.dart | 15 ++++----------- .../test/memory/tracing/tracing_view_test.dart | 5 +---- .../test/test_infra/scenes/memory/default.dart | 8 ++++++++ 6 files changed, 17 insertions(+), 31 deletions(-) diff --git a/packages/devtools_app/test/memory/control/settings_dialog_test.dart b/packages/devtools_app/test/memory/control/settings_dialog_test.dart index ec6dc4e179d..dcb3d845a02 100644 --- a/packages/devtools_app/test/memory/control/settings_dialog_test.dart +++ b/packages/devtools_app/test/memory/control/settings_dialog_test.dart @@ -18,13 +18,6 @@ import '../../test_infra/scenes/scene_test_extensions.dart'; void main() { late MemoryDefaultScene scene; - Future pumpMemoryScreen(WidgetTester tester) async { - await tester.pumpSceneAsync(scene); - // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(MemoryBody), findsOneWidget); - } - // Set a wide enough screen width that we do not run into overflow. const windowSize = Size(2225.0, 1000.0); @@ -41,7 +34,7 @@ void main() { 'settings update preferences', windowSize, (WidgetTester tester) async { - await pumpMemoryScreen(tester); + await scene.pump(tester); // Open the dialog. await tester.tap(find.byType(SettingsOutlinedButton)); diff --git a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart index 295996d62e4..f9536c558eb 100644 --- a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart +++ b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart @@ -15,10 +15,7 @@ import '../../../test_infra/scenes/memory/default.dart'; import '../../../test_infra/scenes/scene_test_extensions.dart'; Future pumpScene(WidgetTester tester, MemoryDefaultScene scene) async { - await tester.pumpSceneAsync(scene); - // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(MemoryBody), findsOneWidget); + await scene.pump(tester); await tester.tap( find.byKey(MemoryScreenKeys.diffTab), ); diff --git a/packages/devtools_app/test/memory/framework/memory_controller_test.dart b/packages/devtools_app/test/memory/framework/memory_controller_test.dart index 3edda6b16be..3ca965f686e 100644 --- a/packages/devtools_app/test/memory/framework/memory_controller_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_controller_test.dart @@ -25,10 +25,8 @@ final _filter2 = ClassFilter( ); Future pumpScene(WidgetTester tester, MemoryDefaultScene scene) async { - await tester.pumpSceneAsync(scene); - // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(MemoryBody), findsOneWidget); + await scene.pump(tester); + await tester.tap( find.byKey(MemoryScreenKeys.diffTab), ); diff --git a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart index 495cc66b163..8f153a9fc5a 100644 --- a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart +++ b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart @@ -27,13 +27,6 @@ void main() { await scene.setUp(); }); - Future pumpMemoryScreen(WidgetTester tester) async { - await tester.pumpScene(scene); - // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(MemoryBody), findsOneWidget); - } - // Set a wide enough screen width that we do not run into overflow. const windowSize = Size(2225.0, 1200.0); //setGlobal(NotificationService, NotificationService()); @@ -57,7 +50,7 @@ void main() { 'respects VM Developer Mode setting', windowSize, (WidgetTester tester) async { - await pumpMemoryScreen(tester); + await scene.pump(tester); final allocationProfileController = scene.controller.profile; @@ -156,7 +149,7 @@ void main() { 'manually refreshes', windowSize, (WidgetTester tester) async { - await pumpMemoryScreen(tester); + await scene.pump(tester); final allocationProfileController = scene.controller.profile; await navigateToAllocationProfile(tester, allocationProfileController); @@ -185,7 +178,7 @@ void main() { 'refreshes on GC', windowSize, (WidgetTester tester) async { - await pumpMemoryScreen(tester); + await scene.pump(tester); final allocationProfileController = scene.controller.profile; @@ -227,7 +220,7 @@ void main() { 'sorts correctly', windowSize, (WidgetTester tester) async { - await pumpMemoryScreen(tester); + await scene.pump(tester); final table = find.byType(FlatTable); expect(table, findsOneWidget); diff --git a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart index 88699704453..c2bc6d70e0b 100644 --- a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart +++ b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart @@ -59,10 +59,7 @@ void main() { late final CpuSamples allocationTracingProfile; Future pumpScene(WidgetTester tester) async { - await tester.pumpSceneAsync(scene); - // Delay to ensure the memory profiler has collected data. - await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(MemoryBody), findsOneWidget); + await scene.pump(tester); await tester.tap( find.byKey(MemoryScreenKeys.dartHeapAllocationTracingTab), ); diff --git a/packages/devtools_app/test/test_infra/scenes/memory/default.dart b/packages/devtools_app/test/test_infra/scenes/memory/default.dart index f2a6eae14a8..1d483cbf86b 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/default.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/default.dart @@ -21,6 +21,7 @@ import '../../../test_infra/test_data/memory.dart'; import '../../../test_infra/test_data/memory_allocation.dart'; import '../../test_data/memory/heap/heap_data.dart'; import '../../test_data/memory/heap/heap_graph_fakes.dart'; +import '../scene_test_extensions.dart'; // To run: // flutter run -t test/test_infra/scenes/memory/default.stager_app.g.dart -d macos @@ -79,6 +80,13 @@ class MemoryDefaultScene extends Scene { ); } + Future pump(WidgetTester tester) async { + await tester.pumpSceneAsync(this); + // Delay to ensure the memory profiler has collected data. + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.byType(MemoryBody), findsOneWidget); + } + @override /// Sets up the scene. From 5d7d3a59fc24f34d8b42af4529b0a52d6ca23e13 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 13 Apr 2024 17:14:02 -0700 Subject: [PATCH 96/97] - --- .../devtools_app/test/memory/control/settings_dialog_test.dart | 2 -- .../devtools_app/test/memory/diff/widgets/diff_pane_test.dart | 1 - .../test/memory/framework/memory_controller_test.dart | 2 -- .../test/memory/profile/allocation_profile_table_view_test.dart | 2 -- .../devtools_app/test/memory/tracing/tracing_view_test.dart | 1 - 5 files changed, 8 deletions(-) diff --git a/packages/devtools_app/test/memory/control/settings_dialog_test.dart b/packages/devtools_app/test/memory/control/settings_dialog_test.dart index dcb3d845a02..65b61648556 100644 --- a/packages/devtools_app/test/memory/control/settings_dialog_test.dart +++ b/packages/devtools_app/test/memory/control/settings_dialog_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:devtools_app/src/screens/memory/framework/memory_screen.dart'; import 'package:devtools_app/src/screens/memory/panes/control/widgets/settings_dialog.dart'; import 'package:devtools_app/src/shared/common_widgets.dart'; import 'package:devtools_app/src/shared/globals.dart'; @@ -13,7 +12,6 @@ import 'package:flutter_test/flutter_test.dart'; import '../../test_infra/matchers/matchers.dart'; import '../../test_infra/scenes/memory/default.dart'; -import '../../test_infra/scenes/scene_test_extensions.dart'; void main() { late MemoryDefaultScene scene; diff --git a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart index f9536c558eb..b61d21dbe7f 100644 --- a/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart +++ b/packages/devtools_app/test/memory/diff/widgets/diff_pane_test.dart @@ -12,7 +12,6 @@ import 'package:flutter_test/flutter_test.dart'; import '../../../test_infra/matchers/matchers.dart'; import '../../../test_infra/scenes/memory/default.dart'; -import '../../../test_infra/scenes/scene_test_extensions.dart'; Future pumpScene(WidgetTester tester, MemoryDefaultScene scene) async { await scene.pump(tester); diff --git a/packages/devtools_app/test/memory/framework/memory_controller_test.dart b/packages/devtools_app/test/memory/framework/memory_controller_test.dart index 3ca965f686e..0bc4cecad4e 100644 --- a/packages/devtools_app/test/memory/framework/memory_controller_test.dart +++ b/packages/devtools_app/test/memory/framework/memory_controller_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/shared/heap/class_filter.dart'; import 'package:devtools_test/helpers.dart'; @@ -10,7 +9,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../test_infra/scenes/memory/default.dart'; -import '../../test_infra/scenes/scene_test_extensions.dart'; final _filter1 = ClassFilter( except: 'filter1', diff --git a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart index 8f153a9fc5a..5390f7f5d42 100644 --- a/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart +++ b/packages/devtools_app/test/memory/profile/allocation_profile_table_view_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:devtools_app/src/screens/memory/framework/memory_screen.dart'; import 'package:devtools_app/src/screens/memory/framework/memory_tabs.dart'; import 'package:devtools_app/src/screens/memory/panes/profile/model.dart'; import 'package:devtools_app/src/screens/memory/panes/profile/profile_pane_controller.dart'; @@ -17,7 +16,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../test_infra/scenes/memory/default.dart'; -import '../../test_infra/scenes/scene_test_extensions.dart'; void main() { late MemoryDefaultScene scene; diff --git a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart index c2bc6d70e0b..4a583e3327f 100644 --- a/packages/devtools_app/test/memory/tracing/tracing_view_test.dart +++ b/packages/devtools_app/test/memory/tracing/tracing_view_test.dart @@ -18,7 +18,6 @@ import 'package:mockito/mockito.dart'; import 'package:vm_service/vm_service.dart'; import '../../test_infra/scenes/memory/default.dart'; -import '../../test_infra/scenes/scene_test_extensions.dart'; import '../../test_infra/utils/test_utils.dart'; // TODO(bkonyi): add tests for multi-isolate support. From 8938b89d6ee623e18e190599eee4f68cba776e64 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 15 Apr 2024 09:46:14 -0700 Subject: [PATCH 97/97] - --- .../lib/src/screens/memory/framework/memory_controller.dart | 2 +- .../screens/memory/framework/offline_data/offline_data.dart | 2 +- .../lib/src/screens/memory/framework/screen_body.dart | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart index 676f59d5a07..39b30441628 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/memory_controller.dart @@ -86,7 +86,7 @@ class MemoryController extends DisposableController assert(!_initialized.isCompleted); switch (_mode) { case DevToolsMode.disconnected: - // TODO: load memory screen in disconnected mode, https://github.com/flutter/devtools/issues/6972 + // TODO(polina-c): load memory screen in disconnected mode, https://github.com/flutter/devtools/issues/6972 _initializeData(); case DevToolsMode.connected: _initializeData( diff --git a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart index faf56a807f2..6588ef67891 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/offline_data/offline_data.dart @@ -24,7 +24,7 @@ class OfflineMemoryData { required this.selectedTab, }); - // TODO: use an extension type for the Json parsing, https://github.com/flutter/devtools/issues/6972 + // TODO(polina-c): use an extension type for the Json parsing, https://github.com/flutter/devtools/issues/6972 // https://github.com/flutter/devtools/pull/7572#discussion_r1563102256 factory OfflineMemoryData.parse(Map json) { Map item(String key) => diff --git a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart index 1b2d857553f..4c67657cf69 100644 --- a/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart +++ b/packages/devtools_app/lib/src/screens/memory/framework/screen_body.dart @@ -7,6 +7,7 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/material.dart'; import '../../../shared/banner_messages.dart'; +import '../../../shared/common_widgets.dart'; import '../../../shared/http/http_service.dart' as http_service; import '../../../shared/screen.dart'; import '../../../shared/utils.dart'; @@ -73,9 +74,7 @@ class _ConnectedMemoryBodyState extends State ], ); } else { - return const Center( - child: CircularProgressIndicator(), - ); + return const CenteredCircularProgressIndicator(); } }, );