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://flutter.dev/docs/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