There are many ways to write a memory test for Flutter. In this article, we give 3 classes of example tests that are currently used by Flutter device lab. Memory performance is a high priority for Flutter so there are many new memory tools and test utilities in progress. We’ll add them in this doc in the future.

## [MemoryTest][class MemoryTest] that interacts with adb directly

These memory tests use the [MemoryTest class defined in the device lab perf_tests.dart][class MemoryTest] to poll adb directly before and after an overridable `useMemory` function. By default, `useMemory` will just run an app in release and wait for a “done” message to be printed in logcat.

Examples include
- [`complex_layout_scroll_perf__memory`][complex layout memory manifest]
  - [device lab task file][complex layout memory task]
  - [main file][complex layout memory main]
- [`fast_scroll_large_images_memory`][fast scroll memory manifest]
  - [device lab task file][fast scroll memory task]
  - [main file][fast scroll memory main]

To write a new MemoryTest case `some_memory_perf` and add it to Flutter’s device lab so Flutter’s CI system can measure it for each Flutter commit, follow examples above to

1. Create a `main` function for the test app in a file named like `test_memory/some_memory_perf.dart`.
2. Add a `some_memory_perf` entry to [manifest.yaml][manifest]
3. Add a `some_memory_perf.dart` file to [dev/devicelab/bin/tasks][tasks] folder.


### Pros
- Low overhead.
- Works in all runtime modes, including release.
- The test has complete control on when to start and stop the memory measurement.

### Cons
- Only have 2 memory readings, begin and end, during the app run.
- Polling ADB may trigger collections of the Java heap.
- Only works on Android targets.
- Requires a test environment with access to ADB.
- Requires a host machine with Flutter SDK installed.

## DevTools Memory Test

The memory tests use DevTools to poll adb and Dart VM during a normal Flutter driver test run, which typically measures speed performance instead of memory performance. [DevToolsMemoryTest][class DevToolsMemoryTest] handles most of the process so a new test only needs to specify the driver test location.

Examples include
- [`complex_layout_scroll_perf__devtools_memory`][complex layout devtools memory manifest]
  - [device lab task file][complex layout devtools memory task]
- [`large_image_changer_perf_android`][large image changer manifest]
  - [device lab task file][large image changer task]

To write a new DevTools memory test case `some_memory_perf` and add it to Flutter’s device lab so Flutter’s CI system can measure it for each Flutter commit, follow examples above to

1. Write (or reuse) a normal Flutter driver test for the app in files named like `test_driver/some_memory_perf.dart` and `test_driver/some_memory_perf_test.dart`.
2. Add a `some_memory_perf` entry to [manifest.yaml][manifest]
3. Add a `some_memory_perf.dart` file to [dev/devicelab/bin/tasks][tasks] folder.

### Pros
- Have finer grained measurements (~1 reading per second).
- Also have Dart VM memory info.
- Can easily turn a speed-focused driver test into a memory test.

### Cons
- Don’t have much control on when to start and stop the measurement.
- Polling ADB may trigger collections on the Java heap.
- Requires a test environment with access to ADB.
- Only works on Android targets.
- Not available for release mode, so may incur extra memory overhead in profile or debug mode.
- Requires a host machine with Flutter SDK installed.

## iOS Memory Test

The iOS embedding of Flutter supports sampling memory usage during runtime, which then writes metrics to the [Dart timeline][Dart timeline]. After recording a timeline for the relevant portion of an application’s execution, the timeline can be analyzed to obtain memory related information from the profile.

Examples include
- [`large_image_changer_perf_ios`][large image changer manifest ios]
  - [device lab task file][large image changer task ios]

To write a new iOS memory test case `some_memory_perf` and add it to Flutter’s device lab so Flutter’s CI system can measure it for each Flutter commit, follow examples above to

1. Write (or reuse) a normal Flutter driver test for the app in files named like `test_driver/some_memory_perf.dart` and `test_driver/some_memory_perf_test.dart`.
2. Add a `some_memory_perf` entry to [manifest.yaml][manifest]
3. Add a `some_memory_perf.dart` file to [dev/devicelab/bin/tasks][tasks] folder that specifies `measureMemory: true`.

### Pros
- Can be run on a machine that does not have the Flutter SDK installed.
- Can adjust the sampling frequency so one can have as many or as few measurements as needed.
- Each sampling has much less overhead compared to calling adb
- Flutter driver tests on iOS get memory measurements for free.

### Cons
- Only works on iOS targets.
- Not available for release mode, so may incur extra memory overhead in profile or debug mode.
- Memory polling mechanism may incur additional memory overhead.


[manifest]: https://github.com/flutter/flutter/blob/main/dev/devicelab/manifest.yaml

[tasks]: https://github.com/flutter/flutter/tree/main/dev/devicelab/bin/tasks

[class MemoryTest]: https://github.com/flutter/flutter/blob/51bb11f7cece47840a9ee6d6d43db97ab16b31df/dev/devicelab/lib/tasks/perf_tests.dart#L941

[complex layout memory manifest]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/manifest.yaml#L329

[complex layout memory task]: https://github.com/flutter/flutter/blob/main/dev/devicelab/bin/tasks/complex_layout_scroll_perf__memory.dart

[complex layout memory main]: https://github.com/flutter/flutter/blob/main/dev/benchmarks/complex_layout/test_memory/scroll_perf.dart

[fast scroll memory manifest]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/manifest.yaml#L837

[fast scroll memory task]: https://github.com/flutter/flutter/blob/main/dev/devicelab/bin/tasks/fast_scroll_large_images__memory.dart

[fast scroll memory main]: https://github.com/flutter/flutter/blob/main/dev/benchmarks/macrobenchmarks/test_memory/large_images.dart

[class DevToolsMemoryTest]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/lib/tasks/perf_tests.dart#L1138

[complex layout devtools memory manifest]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/manifest.yaml#L359

[complex layout devtools memory task]: https://github.com/flutter/flutter/blob/main/dev/devicelab/bin/tasks/complex_layout_scroll_perf__devtools_memory.dart

[large image changer manifest]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/manifest.yaml#L874

[large image changer task]: https://github.com/flutter/flutter/blob/main/dev/devicelab/bin/tasks/large_image_changer_perf_android.dart

[Dart timeline]:https://docs.flutter.dev/development/tools/devtools/timeline

[large image changer manifest ios]: https://github.com/flutter/flutter/blob/7e41425d4af21dec7a7ff072a3ec1387859e32c8/dev/devicelab/manifest.yaml#L880

[large image changer task ios]: https://github.com/flutter/flutter/blob/main/dev/devicelab/bin/tasks/large_image_changer_perf_ios.dart
