Coming soon! See https://github.com/flutter/devtools/issues/3951.

The text below is under construction.

Detect Memory Leaks

This page describes how to auto-detect certain types of memory leaks in Dart and Flutter applications and tests. See other information on memory leaks here.

Quick start to track leaks for Flutter

Flutter application

  1. Add leak_tracker to dependencies in pubspec.yaml.

  2. Before runApp invocation, enable leak tracking, and connect the Flutter memory allocation events:

import 'package:flutter/foundation.dart';
import 'package:leak_tracker/leak_tracker.dart';

...

enableLeakTracking();
MemoryAllocations.instance
      .addListener((ObjectEvent event) => dispatchObjectEvent(event.toMap()));
runApp(...

  1. Run the application in debug mode and watch for a leak related warnings. If you see a warning, open the link to investigate the leaks.

TODO(polina-c): implement the link and add example of the warning.

Flutter tests

Wrap your tests with withLeakTracking to setup automated leak verification:

test('...', () async {
  final leaks = await withLeakTracking(
    () async {
      ...
    },
  );

  expect(leaks, leakFree);
});

Limitations

By platform

Leak tracker does not work for web platform.

By tracked classes

The leak tracker will catch leaks only for instrumented objects (See concepts for details).

However, the good news is:

  1. Most disposable Flutter Framework classes include instrumentation. If how your Flutter app manages widgets results in leaks, Flutter will catch them.

  2. If a leak involves at least one instrumented object, the leak will be caught and all other objects, even non-instrumented, will stop leaking as well.

See the instrumentation guidance.

By build mode

The leak tracker availability differs by build modes. See Dart build modes or Flutter build modes.

Dart development and Flutter debug

Leak tracking is fully available.

Flutter profile

Leak tracking is available, but MemoryAllocations that listens to Flutter instrumented objects, should be turned on if you want to track Flutter Framework objects.

Dart production and Flutter release

Leak tracking is disabled.

NOTE: If you are interested in enabling leak tracking for release mode, please, comment here.

Instrument your code

If you want to catch leaks for objects outside of Flutter Framework (that are already instrumented), you need to instrument them.

For each tracked object the library should get two signals from your code: (1) the object is created and (2) the object is not in use. It is most convenient to give the first signal in the constructor and the second signal in the dispose method:

import 'package:leak_tracker/src/leak_tracker.dart';

class InstrumentedClass {
  InstrumentedClass() {
    dispatchObjectCreated(
      library: library,
      className: '$InstrumentedClass',
      object: this,
    );
  }

  static const library = 'package:my_package/lib/src/my_lib.dart';

  void dispose() {
    dispatchObjectDisposed(object: this);
  }
}

Start/stop leak tracking

To start leak tracking, invoke enableLeakTracking(), to stop: disableLeakTracking().

TODO(polina-c): note that Flutter Framework enables leak tracking by default, when it is the case.

Collect leaks

There are two steps in leak collection: (1) get signal that leaks happened (leak summary) and (2) get details about the leaks.

By default, the leak tracker checks for leaks every second, and, if there are some, outputs the summary to console and sends it to DevTools. Then you can get leak details either by requesting them from DevTools or by invoking collectLeaks() programmatically.

You can change the default behavior by passing customized configuration to enableLeakTracking():

  1. Disable regular leak checking and check the leaks by calling checkLeaks().
  2. Disable output to console or to DevTools.
  3. Listen to the leaks with custom handler.

See DevTools > Memory > Leaks guidance on how to interact with leak tracker.

TODO: add link to DevTools documentation.

Performance impact

Memory

The Leak Tracker stores a small additional record for each tracked alive object and for each detected leak, that increases the memory footprint.

For the Gallery application in profile mode on macos the leak tracking increased memory footprint of the home page by ~400 KB that is ~0.5% of the total.

CPU

Leak tracking impacts CPU in two areas:

  1. Per object tracking. Added ~0.05 of millisecond (~2.7%) to the total load time of Gallery home page in profile mode on macos.

  2. Regular asynchronous analysis of the tracked objects. Took ~2.5 millisectonds for Gallery home page in profile mode on macos.