flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.32k stars 27.53k forks source link

Flutter instances don't release all memory when window is closed in multi-window macOS application. #96487

Open KevinBrendel opened 2 years ago

KevinBrendel commented 2 years ago

Details

Launching additional flutter windows on macOS using the following Swift code:

let window = MainFlutterWindow()
window.initializeFlutter()
window.styleMask = styleMask
window.setFrame(frame, display: true)

let windowController = NSWindowController()
windowController.window = window
windowController.showWindow(self)

window.initializeFlutter() mostly consists of the initialization code that is placed in awakeFromNib() per default. For a complete minimal example project based on the default template, see this repository: https://github.com/KevinBrendel/flutter_macos_multi_window_memory

When closing a window, the allocated memory for this window is not released.

I managed to reduce the memory allocation by calling shutDownEngine(), but still a lot of memory remains allocated.

Screenshot 2022-01-11 at 23 26 36

This issue occurs on both the current stable and master channels.

Target Platform: macOS Target OS version/browser: 12.1 Devices: MacBook Pro (16-inch, 2021) Architecture: Apple Silicon / ARM64 (M1 Max)

Logs

Logs ``` Analyzing flutter_macos_multi_window_memory... No issues found! (ran in 1.7s) ``` ``` [✓] Flutter (Channel master, 2.9.0-1.0.pre.322, on macOS 12.1 21C52 darwin-arm, locale en-DE) • Flutter version 2.9.0-1.0.pre.322 at /Users/kevin/SDKs/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 9490917408 (4 hours ago), 2022-01-11 13:00:12 -0600 • Engine revision a79a3bac0c • Dart version 2.16.0 (build 2.16.0-154.0.dev) • DevTools version 2.9.2 [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/kevin/Library/Android/sdk • Platform android-32, build-tools 32.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) [✓] VS Code (version 1.63.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.32.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-arm64 • macOS 12.1 21C52 darwin-arm • Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.71 [✓] HTTP Host Availability • All required HTTP hosts are available ```
danagbemava-nc commented 2 years ago

Reproducible on stable and master

Steps to reproduce

Can't share the instruments files because the sizes are too large for GH.

zipped code sample [flutter_macos_multi_window_memory.zip](https://github.com/flutter/flutter/files/7854815/flutter_macos_multi_window_memory.zip)
screenshot and video Screenshot 2022-01-12 at 13 18 02 https://user-images.githubusercontent.com/88313112/149151324-a77f9387-a8dd-4aac-9119-5d991b020aa5.mov
flutter doctor -v ```console [✓] Flutter (Channel stable, 2.8.1, on macOS 11.6 20G165 darwin-arm, locale en-GB) • Flutter version 2.8.1 at /Users/nexus/dev/sdks/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 77d935af4d (4 weeks ago), 2021-12-16 08:37:33 -0800 • Engine revision 890a5fca2e • Dart version 2.15.1 [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) • Android SDK at /Users/nexus/Library/Android/sdk • Platform android-31, build-tools 31.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 13.0) • Xcode at /Applications/Xcode.app/Contents/Developer • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) [☠] IntelliJ IDEA Community Edition (the doctor check crashed) ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, please let us know about this issue at https://github.com/flutter/flutter/issues. ✗ FormatException: Unexpected extension byte (at offset 5) • #0 _Utf8Decoder.convertSingle (dart:convert-patch/convert_patch.dart:1789:7) #1 Utf8Decoder.convert (dart:convert/utf.dart:318:42) #2 InputStream.readString (package:archive/src/util/input_stream.dart:207:30) #3 new ZipDirectory.read (package:archive/src/zip/zip_directory.dart:40:30) #4 ZipDecoder.decodeBuffer (package:archive/src/zip_decoder.dart:19:30) #5 ZipDecoder.decodeBytes (package:archive/src/zip_decoder.dart:14:12) #6 IntelliJPlugins._findPluginXml (package:flutter_tools/src/intellij/intellij.dart:130:44) #7 IntelliJPlugins._readPackageVersion (package:flutter_tools/src/intellij/intellij.dart:141:40) #8 IntelliJPlugins.validatePackage (package:flutter_tools/src/intellij/intellij.dart:63:35) #9 IntelliJValidator.validate (package:flutter_tools/src/intellij/intellij_validator.dart:103:15) #10 asyncGuard. (package:flutter_tools/src/base/async_guard.dart:111:32) #11 asyncGuard. (package:flutter_tools/src/base/async_guard.dart:109:18) #12 _rootRun (dart:async/zone.dart:1428:13) #13 _CustomZone.run (dart:async/zone.dart:1328:19) #14 _runZoned (dart:async/zone.dart:1863:10) #15 runZonedGuarded (dart:async/zone.dart:1851:12) #16 runZoned (dart:async/zone.dart:1782:12) #17 asyncGuard (package:flutter_tools/src/base/async_guard.dart:109:3) #18 Doctor.startValidatorTasks (package:flutter_tools/src/doctor.dart:197:9) #19 Doctor.diagnose (package:flutter_tools/src/doctor.dart:301:47) #20 DoctorCommand.runCommand (package:flutter_tools/src/commands/doctor.dart:53:47) #21 FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:1290:12) #22 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:1140:27) #23 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) #24 CommandRunner.runCommand (package:args/command_runner.dart:209:13) #25 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:288:9) #26 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) #27 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:236:5) #28 run.. (package:flutter_tools/runner.dart:62:9) #29 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) #30 main (package:flutter_tools/executable.dart:94:3) [✓] VS Code (version 1.63.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.32.0 [✓] Connected device (3 available) • Nexus (mobile) • • ios • iOS 15.0.2 19A404 • macOS (desktop) • macos • darwin-arm64 • macOS 11.6 20G165 darwin-arm • Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.71 ! Doctor found issues in 1 category. ``` ```console [✓] Flutter (Channel master, 2.9.0-1.0.pre.328, on macOS 11.6 20G165 darwin-arm, locale en-GB) • Flutter version 2.9.0-1.0.pre.328 at /Users/nexus/dev/sdks/flutters • Upstream repository https://github.com/flutter/flutter.git • Framework revision d290763941 (11 hours ago), 2022-01-11 18:20:14 -0800 • Engine revision 643b2787f4 • Dart version 2.16.0 (build 2.16.0-159.0.dev) • DevTools version 2.9.2 [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) • Android SDK at /Users/nexus/Library/Android/sdk • Platform android-31, build-tools 31.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 13.0) • Xcode at /Applications/Xcode.app/Contents/Developer • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189) [✓] IntelliJ IDEA Community Edition (version 2021.3) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin version 213.5744.122 [✓] VS Code (version 1.63.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.32.0 [✓] Connected device (3 available) • Nexus (mobile) • • ios • iOS 15.0.2 19A404 • macOS (desktop) • macos • darwin-arm64 • macOS 11.6 20G165 darwin-arm • Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.71 [✓] HTTP Host Availability • All required HTTP hosts are available • No issues found! ```
zhongwuzw commented 2 years ago

The demo has the retain cycle, please break the cycle and try again. https://github.com/KevinBrendel/flutter_macos_multi_window_memory/blob/df9014c56d865a831dab270df892dfcf303f3393/macos/Runner/MainFlutterWindow.swift?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L17

KevinBrendel commented 2 years ago

Thanks for the suggestion. I am pretty new to Swift, so to be sure, I completely removed the MethodChannel and replaced it with a native menu option (Window -> New Window or CMD+N).

This seems to have increased the amount of memory that is released when closing a window, but still, a large portion remains allocated.

Screenshot 2022-01-15 at 19 58 00

chinmaygarde commented 2 years ago

cc @cbracken This could also be the instance of the VM that is running after the engine instance goes away. The fix is to explicitly tell the engine to shutdown the VM when the last instance goes away. Today, the VM stays up so that subsequent isolate launches during resume etc. are faster than first launch.

KevinBrendel commented 2 years ago

That definitely sounds like it would cause this issue. Is there some way for me to configure the engine to shut down the VM to test this (without compiling my own version of Flutter)?

chinmaygarde commented 2 years ago

without compiling my own version of Flutter

It's part of the public Embedder API but I am not sure if the embedder hides this in turn. Which is why I pinged @cbracken .