From b1389acc2cfc598f823c9719ff657c86b23fa471 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:12:49 +0200 Subject: [PATCH 1/2] Remove memoryObserver feature flag --- .../lib/src/framework/framework_core.dart | 11 ----------- .../src/screens/app_size/app_size_controller.dart | 11 ++++------- .../lib/src/screens/logging/logging_controller.dart | 13 +++++-------- .../screens/memory/framework/memory_controller.dart | 11 ++++------- .../lib/src/screens/network/network_controller.dart | 5 +---- .../screens/performance/performance_controller.dart | 5 +---- .../profiler/profiler_screen_controller.dart | 7 ++----- .../devtools_app/lib/src/shared/feature_flags.dart | 10 ---------- .../framework/observer/memory_observer_test.dart | 9 --------- .../profiler_screen_controller_test.dart | 4 ---- .../screens/logging/logging_controller_test.dart | 9 +-------- .../memory/framework/memory_controller_test.dart | 8 -------- .../test/shared/primitives/feature_flags_test.dart | 1 - 13 files changed, 18 insertions(+), 86 deletions(-) diff --git a/packages/devtools_app/lib/src/framework/framework_core.dart b/packages/devtools_app/lib/src/framework/framework_core.dart index f141b010897..f5f78a11ee3 100644 --- a/packages/devtools_app/lib/src/framework/framework_core.dart +++ b/packages/devtools_app/lib/src/framework/framework_core.dart @@ -23,7 +23,6 @@ import '../service/vm_service_wrapper.dart'; import '../shared/analytics/analytics.dart' as ga; import '../shared/config_specific/framework_initialize/framework_initialize.dart'; import '../shared/console/eval/eval_service.dart'; -import '../shared/feature_flags.dart'; import '../shared/framework/app_error_handling.dart' as error_handling; import '../shared/framework/framework_controller.dart'; import '../shared/framework/screen_controllers.dart'; @@ -37,7 +36,6 @@ import '../shared/preferences/preferences.dart'; import '../shared/primitives/message_bus.dart'; import '../shared/server/server.dart' as server; import '../shared/utils/utils.dart'; -import 'observer/memory_observer.dart'; import 'theme_manager.dart'; typedef ErrorReporter = void Function(String title, Object error); @@ -46,8 +44,6 @@ final _log = Logger('framework_core'); /// A namespace for core framework objects and methods. extension FrameworkCore on Never { - static final _memoryObserver = MemoryObserver(); - /// Initializes the DevTools framework, which includes setting up global /// variables, local storage, preferences, and initializing framework level /// managers like the Dart Tooling Daemon manager and the DevTools extensions @@ -83,10 +79,6 @@ extension FrameworkCore on Never { // This must be called after the DTD connection has been initialized and after // preferences have been initialized. await extensionService.initialize(); - - if (FeatureFlags.memoryObserver.isEnabled) { - _memoryObserver.init(); - } } /// Disposes framework level services and managers. @@ -99,9 +91,6 @@ extension FrameworkCore on Never { preferences.dispose(); _themeManager?.dispose(); unawaited(dtdManager.dispose()); - if (FeatureFlags.memoryObserver.isEnabled) { - _memoryObserver.dispose(); - } } static void _initGlobals() { diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart index ecc58a47bfa..96f06a566e5 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_controller.dart @@ -11,7 +11,6 @@ import 'package:vm_snapshot_analysis/utils.dart'; import 'package:vm_snapshot_analysis/v8_profile.dart'; import '../../shared/charts/treemap.dart'; -import '../../shared/feature_flags.dart'; import '../../shared/framework/screen.dart'; import '../../shared/framework/screen_controllers.dart'; import '../../shared/primitives/utils.dart'; @@ -772,12 +771,10 @@ class AppSizeController extends DevToolsScreenController { @override void releaseMemory({bool partial = false}) { - if (FeatureFlags.memoryObserver.isEnabled) { - // This behavior is the same regardless of the value of `partial`. We can - // implement a partial clearing if it becomes necessary. - clear(AppSizeScreen.analysisTabKey); - clear(AppSizeScreen.diffTabKey); - } + // This behavior is the same regardless of the value of `partial`. We can + // implement a partial clearing if it becomes necessary. + clear(AppSizeScreen.analysisTabKey); + clear(AppSizeScreen.diffTabKey); } } diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index 9563c10a439..8f9818c584a 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -18,7 +18,6 @@ import 'package:vm_service/vm_service.dart'; import '../../service/vm_service_wrapper.dart'; import '../../shared/diagnostics/diagnostics_node.dart'; import '../../shared/diagnostics/inspector_service.dart'; -import '../../shared/feature_flags.dart'; import '../../shared/framework/app_error_handling.dart' as error_handling; import '../../shared/framework/screen.dart'; import '../../shared/framework/screen_controllers.dart'; @@ -805,13 +804,11 @@ class LoggingController extends DevToolsScreenController @override void releaseMemory({bool partial = false}) { - if (FeatureFlags.memoryObserver.isEnabled) { - if (partial) { - // Trim logs from the front so that the oldest logs are removed. - _updateData(data.sublist(data.length ~/ 2)); - } else { - clear(); - } + if (partial) { + // Trim logs from the front so that the oldest logs are removed. + _updateData(data.sublist(data.length ~/ 2)); + } else { + clear(); } } } 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 3f2a8f10374..62c0bb92e6d 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 @@ -10,7 +10,6 @@ import 'dart:async'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import '../../../shared/feature_flags.dart'; import '../../../shared/framework/screen.dart'; import '../../../shared/framework/screen_controllers.dart'; import '../../../shared/globals.dart'; @@ -217,11 +216,9 @@ class MemoryController extends DevToolsScreenController @override FutureOr releaseMemory({bool partial = false}) async { - if (FeatureFlags.memoryObserver.isEnabled) { - diff.clearSnapshots(partial: partial); - // Clear all allocation traces since the traces form a single tracing - // profile. - await trace?.clear(); - } + diff.clearSnapshots(partial: partial); + // Clear all allocation traces since the traces form a single tracing + // profile. + await trace?.clear(); } } diff --git a/packages/devtools_app/lib/src/screens/network/network_controller.dart b/packages/devtools_app/lib/src/screens/network/network_controller.dart index 1547315de50..62fd5c537eb 100644 --- a/packages/devtools_app/lib/src/screens/network/network_controller.dart +++ b/packages/devtools_app/lib/src/screens/network/network_controller.dart @@ -11,7 +11,6 @@ import 'package:vm_service/vm_service.dart'; import '../../shared/config_specific/import_export/import_export.dart'; import '../../shared/config_specific/logger/allowed_error.dart'; -import '../../shared/feature_flags.dart'; import '../../shared/framework/screen.dart'; import '../../shared/framework/screen_controllers.dart'; import '../../shared/globals.dart'; @@ -515,9 +514,7 @@ class NetworkController extends DevToolsScreenController @override FutureOr releaseMemory({bool partial = false}) async { - if (FeatureFlags.memoryObserver.isEnabled) { - await clear(partial: partial); - } + await clear(partial: partial); } } diff --git a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart index 85424fea25b..8bed01cc548 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart @@ -14,7 +14,6 @@ import 'package:vm_service/vm_service.dart'; import '../../service/service_registrations.dart' as registrations; import '../../shared/diagnostics/inspector_service.dart'; -import '../../shared/feature_flags.dart'; import '../../shared/framework/screen.dart'; import '../../shared/framework/screen_controllers.dart'; import '../../shared/globals.dart'; @@ -291,9 +290,7 @@ class PerformanceController extends DevToolsScreenController @override FutureOr releaseMemory({bool partial = false}) async { - if (FeatureFlags.memoryObserver.isEnabled) { - await clearData(partial: partial, clearVmTimeline: !partial); - } + await clearData(partial: partial, clearVmTimeline: !partial); } } diff --git a/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart b/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart index af58b7af68d..6086b47d229 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen_controller.dart @@ -9,7 +9,6 @@ import 'package:flutter/foundation.dart'; import 'package:vm_service/vm_service.dart'; import '../../shared/config_specific/logger/allowed_error.dart'; -import '../../shared/feature_flags.dart'; import '../../shared/framework/screen.dart'; import '../../shared/framework/screen_controllers.dart'; import '../../shared/globals.dart'; @@ -188,9 +187,7 @@ class ProfilerScreenController extends DevToolsScreenController @override FutureOr releaseMemory({bool partial = false}) async { - if (FeatureFlags.memoryObserver.isEnabled) { - // There is no way to partially release memory for this screen. - await clear(); - } + // There is no way to partially release memory for this screen. + await clear(); } } diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index d885a3e460e..b6c8627d190 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -44,15 +44,6 @@ bool get enableBeta => enableExperiments || !isExternalBuild; /// to the [_booleanFlags] or [_flutterChannelFlags] map for debugging /// purposes. extension FeatureFlags on Never { - /// Flag to enable the DevTools memory observer, which attempts to help users - /// avoid OOM crashes. - /// - /// https://github.com/flutter/devtools/issues/7002 - static final memoryObserver = BooleanFeatureFlag( - name: 'memoryObserver', - enabled: true, - ); - /// Flag to enable save/load for the Memory screen. /// /// https://github.com/flutter/devtools/issues/8019 @@ -115,7 +106,6 @@ extension FeatureFlags on Never { /// When adding a new boolean flag, you are responsible for adding it to this /// map as well. static final _booleanFlags = { - memoryObserver, memorySaveLoad, networkSaveLoad, devToolsExtensions, diff --git a/packages/devtools_app/test/framework/observer/memory_observer_test.dart b/packages/devtools_app/test/framework/observer/memory_observer_test.dart index fb2ec91e589..1e3dfbe6848 100644 --- a/packages/devtools_app/test/framework/observer/memory_observer_test.dart +++ b/packages/devtools_app/test/framework/observer/memory_observer_test.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/framework/observer/memory_observer.dart'; -import 'package:devtools_app/src/shared/feature_flags.dart'; import 'package:devtools_app/src/shared/primitives/byte_utils.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:devtools_test/devtools_test.dart'; @@ -36,10 +35,6 @@ void main() { return memoryUsageBytes; } - setUpAll(() { - FeatureFlags.memoryObserver.setEnabledForTests(true); - }); - setUp(() { measurementComplete = Completer(); observer = MemoryObserver( @@ -57,10 +52,6 @@ void main() { observer.dispose(); }); - tearDownAll(() { - FeatureFlags.memoryObserver.setEnabledForTests(false); - }); - test( 'does not add banner message when memory limit is not reached', () async { diff --git a/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_controller_test.dart b/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_controller_test.dart index fca74716c28..799f30c9f93 100644 --- a/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_controller_test.dart +++ b/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_controller_test.dart @@ -4,7 +4,6 @@ import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/screens/profiler/cpu_profiler_controller.dart'; -import 'package:devtools_app/src/shared/feature_flags.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:devtools_test/devtools_test.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -18,7 +17,6 @@ void main() { late ProfilerScreenController controller; setUp(() { - FeatureFlags.memoryObserver.setEnabledForTests(true); final fakeServiceConnection = FakeServiceConnectionManager( service: FakeServiceManager.createFakeService( cpuSamples: CpuSamples.parse(goldenCpuSamplesJson), @@ -63,7 +61,6 @@ void main() { }); test('releaseMemory', () async { - FeatureFlags.memoryObserver.setEnabledForTests(true); await controller.cpuProfilerController.loadAllSamples(); expect(controller.cpuProfilerController.dataNotifier.value, isNotNull); expect( @@ -75,7 +72,6 @@ void main() { controller.cpuProfilerController.dataNotifier.value, CpuProfilerController.baseStateCpuProfileData, ); - FeatureFlags.memoryObserver.setEnabledForTests(false); }); }); } diff --git a/packages/devtools_app/test/screens/logging/logging_controller_test.dart b/packages/devtools_app/test/screens/logging/logging_controller_test.dart index 5dac954bb91..f086def3476 100644 --- a/packages/devtools_app/test/screens/logging/logging_controller_test.dart +++ b/packages/devtools_app/test/screens/logging/logging_controller_test.dart @@ -8,7 +8,6 @@ library; import 'dart:convert'; import 'package:devtools_app/devtools_app.dart'; -import 'package:devtools_app/src/shared/feature_flags.dart'; import 'package:devtools_app/src/shared/primitives/message_bus.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:devtools_test/devtools_test.dart'; @@ -338,14 +337,9 @@ void main() { group('releaseMemory', () { setUp(() { - FeatureFlags.memoryObserver.setEnabledForTests(true); prepareTestLogs(); }); - tearDown(() { - FeatureFlags.memoryObserver.setEnabledForTests(false); - }); - test('releaseMemory - full release', () { expect(controller.data, isNotEmpty); expect(controller.filteredData.value, isNotEmpty); @@ -366,8 +360,7 @@ void main() { group('LogData', () { test( - 'pretty prints when details are json, and returns its details otherwise.', - () { + 'pretty prints when details are json, and returns its details otherwise.', () { final nonJson = LogData('some kind', 'Not json', 0); final json = LogData( 'some kind', diff --git a/packages/devtools_app/test/screens/memory/framework/memory_controller_test.dart b/packages/devtools_app/test/screens/memory/framework/memory_controller_test.dart index 2fcc090b5a7..2a0dcb30780 100644 --- a/packages/devtools_app/test/screens/memory/framework/memory_controller_test.dart +++ b/packages/devtools_app/test/screens/memory/framework/memory_controller_test.dart @@ -7,7 +7,6 @@ import 'dart:io'; import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/screens/memory/shared/heap/class_filter.dart'; -import 'package:devtools_app/src/shared/feature_flags.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:devtools_test/devtools_test.dart'; import 'package:devtools_test/helpers.dart'; @@ -106,13 +105,6 @@ void main() { ); group('release memory', () { - setUp(() { - FeatureFlags.memoryObserver.setEnabledForTests(true); - }); - - tearDown(() { - FeatureFlags.memoryObserver.setEnabledForTests(false); - }); testWidgetsWithWindowSize('full release', _windowSize, ( WidgetTester tester, diff --git a/packages/devtools_app/test/shared/primitives/feature_flags_test.dart b/packages/devtools_app/test/shared/primitives/feature_flags_test.dart index bc5f69d0867..3939d5561c1 100644 --- a/packages/devtools_app/test/shared/primitives/feature_flags_test.dart +++ b/packages/devtools_app/test/shared/primitives/feature_flags_test.dart @@ -16,7 +16,6 @@ void main() { expect(enableExperiments, false); expect(enableBeta, false); expect(isExternalBuild, true); - expect(FeatureFlags.memoryObserver.isEnabled, true); expect(FeatureFlags.memorySaveLoad.isEnabled, false); expect(FeatureFlags.networkSaveLoad.isEnabled, true); expect(FeatureFlags.devToolsExtensions.isEnabled, isExternalBuild); From fbf25f8d94fd3a9b8b50baff07bb8fef6499b21f Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:34:26 +0200 Subject: [PATCH 2/2] Clean up --- packages/devtools_app/lib/src/framework/framework_core.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/devtools_app/lib/src/framework/framework_core.dart b/packages/devtools_app/lib/src/framework/framework_core.dart index f5f78a11ee3..36ceed556b1 100644 --- a/packages/devtools_app/lib/src/framework/framework_core.dart +++ b/packages/devtools_app/lib/src/framework/framework_core.dart @@ -44,6 +44,8 @@ final _log = Logger('framework_core'); /// A namespace for core framework objects and methods. extension FrameworkCore on Never { + static final _memoryObserver = MemoryObserver(); + /// Initializes the DevTools framework, which includes setting up global /// variables, local storage, preferences, and initializing framework level /// managers like the Dart Tooling Daemon manager and the DevTools extensions @@ -79,6 +81,8 @@ extension FrameworkCore on Never { // This must be called after the DTD connection has been initialized and after // preferences have been initialized. await extensionService.initialize(); + + _memoryObserver.init(); } /// Disposes framework level services and managers. @@ -91,6 +95,7 @@ extension FrameworkCore on Never { preferences.dispose(); _themeManager?.dispose(); unawaited(dtdManager.dispose()); + _memoryObserver.dispose(); } static void _initGlobals() {