Unverified Commit b5ed913e authored by Dan Field's avatar Dan Field Committed by GitHub

Memory/cpu/gpu benchmark for showing large images in succession (#64762)

parent 3aa0243a
lib/generated_plugin_registrant.dart lib/generated_plugin_registrant.dart
devtools_memory.json
...@@ -8,6 +8,7 @@ const String kBackdropFilterRouteName = '/backdrop_filter'; ...@@ -8,6 +8,7 @@ const String kBackdropFilterRouteName = '/backdrop_filter';
const String kPostBackdropFilterRouteName = '/post_backdrop_filter'; const String kPostBackdropFilterRouteName = '/post_backdrop_filter';
const String kSimpleAnimationRouteName = '/simple_animation'; const String kSimpleAnimationRouteName = '/simple_animation';
const String kPictureCacheRouteName = '/picture_cache'; const String kPictureCacheRouteName = '/picture_cache';
const String kLargeImageChangerRouteName = '/large_image_changer';
const String kLargeImagesRouteName = '/large_images'; const String kLargeImagesRouteName = '/large_images';
const String kTextRouteName = '/text'; const String kTextRouteName = '/text';
const String kAnimatedPlaceholderRouteName = '/animated_placeholder'; const String kAnimatedPlaceholderRouteName = '/animated_placeholder';
......
...@@ -3,18 +3,20 @@ ...@@ -3,18 +3,20 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:macrobenchmarks/src/color_filter_and_fade.dart';
import 'package:macrobenchmarks/src/heavy_grid_view.dart';
import 'package:macrobenchmarks/src/large_images.dart';
import 'package:macrobenchmarks/src/picture_cache.dart';
import 'common.dart'; import 'common.dart';
import 'src/animated_placeholder.dart'; import 'src/animated_placeholder.dart';
import 'src/backdrop_filter.dart'; import 'src/backdrop_filter.dart';
import 'src/color_filter_and_fade.dart';
import 'src/cubic_bezier.dart'; import 'src/cubic_bezier.dart';
import 'src/cull_opacity.dart'; import 'src/cull_opacity.dart';
import 'src/filtered_child_animation.dart'; import 'src/filtered_child_animation.dart';
import 'src/heavy_grid_view.dart';
import 'src/large_image_changer.dart';
import 'src/large_images.dart';
import 'src/multi_widget_construction.dart'; import 'src/multi_widget_construction.dart';
import 'src/picture_cache.dart';
import 'src/post_backdrop_filter.dart'; import 'src/post_backdrop_filter.dart';
import 'src/simple_animation.dart'; import 'src/simple_animation.dart';
import 'src/simple_scroll.dart'; import 'src/simple_scroll.dart';
...@@ -40,6 +42,7 @@ class MacrobenchmarksApp extends StatelessWidget { ...@@ -40,6 +42,7 @@ class MacrobenchmarksApp extends StatelessWidget {
kPostBackdropFilterRouteName: (BuildContext context) => PostBackdropFilterPage(), kPostBackdropFilterRouteName: (BuildContext context) => PostBackdropFilterPage(),
kSimpleAnimationRouteName: (BuildContext context) => SimpleAnimationPage(), kSimpleAnimationRouteName: (BuildContext context) => SimpleAnimationPage(),
kPictureCacheRouteName: (BuildContext context) => PictureCachePage(), kPictureCacheRouteName: (BuildContext context) => PictureCachePage(),
kLargeImageChangerRouteName: (BuildContext context) => LargeImageChangerPage(),
kLargeImagesRouteName: (BuildContext context) => LargeImagesPage(), kLargeImagesRouteName: (BuildContext context) => LargeImagesPage(),
kTextRouteName: (BuildContext context) => TextPage(), kTextRouteName: (BuildContext context) => TextPage(),
kAnimatedPlaceholderRouteName: (BuildContext context) => AnimatedPlaceholderPage(), kAnimatedPlaceholderRouteName: (BuildContext context) => AnimatedPlaceholderPage(),
...@@ -162,6 +165,13 @@ class HomePage extends StatelessWidget { ...@@ -162,6 +165,13 @@ class HomePage extends StatelessWidget {
Navigator.pushNamed(context, kHeavyGridViewRouteName); Navigator.pushNamed(context, kHeavyGridViewRouteName);
}, },
), ),
RaisedButton(
key: const Key(kLargeImageChangerRouteName),
child: const Text('Large Image Changer'),
onPressed: () {
Navigator.pushNamed(context, kLargeImageChangerRouteName);
},
),
], ],
), ),
); );
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
/// Displays a new (from image cache's perspective) large image every 500ms.
class LargeImageChangerPage extends StatefulWidget {
@override
_LargeImageChangerState createState() => _LargeImageChangerState();
}
class _LargeImageChangerState extends State<LargeImageChangerPage> {
Timer _timer;
int imageIndex = 0;
ImageProvider currentImage;
@override
void didChangeDependencies() {
super.didChangeDependencies();
currentImage = ResizeImage(
const ExactAssetImage('assets/999x1000.png'),
width: (MediaQuery.of(context).size.width * 2).toInt() + imageIndex,
height: (MediaQuery.of(context).size.height * 2).toInt() + imageIndex,
allowUpscaling: true,
);
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 3), (Timer timer) {
currentImage.evict().then((_) {
setState(() {
imageIndex = (imageIndex + 1) % 6;
currentImage = ResizeImage(
const ExactAssetImage('assets/999x1000.png'),
width: (MediaQuery.of(context).size.width * 2).toInt() + imageIndex,
height: (MediaQuery.of(context).size.height * 2).toInt() + imageIndex,
allowUpscaling: true,
);
});
});
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Image(image: currentImage);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:macrobenchmarks/common.dart';
import 'package:macrobenchmarks/main.dart';
Future<void> main() async {
enableFlutterDriverExtension(handler: (String message) async {
if (message == 'getTargetPlatform') {
return defaultTargetPlatform.toString();
}
throw UnsupportedError('Message $message unsupported');
});
runApp(const MacrobenchmarksApp(initialRoute: kLargeImageChangerRouteName));
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
Future<void> main() async {
const String fileName = 'large_image_changer';
test('Animate for 20 seconds', () async {
final FlutterDriver driver = await FlutterDriver.connect();
await driver.forceGC();
final String targetPlatform = await driver.requestData('getTargetPlatform');
Timeline timeline;
switch (targetPlatform) {
case 'TargetPlatform.iOS':
{
timeline = await driver.traceAction(() async {
await Future<void>.delayed(const Duration(seconds: 20));
});
}
break;
case 'TargetPlatorm.android':
{
// Just run for 20 seconds to collect memory usage. The widget itself
// animates during this time.
await Future<void>.delayed(const Duration(seconds: 20));
}
break;
default:
throw UnsupportedError('Unsupported platform $targetPlatform');
}
if (timeline != null) {
final TimelineSummary summary = TimelineSummary.summarize(timeline);
await summary.writeSummaryToFile(fileName, pretty: true);
await summary.writeTimelineToFile(fileName, pretty: true);
}
await driver.close();
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart';
import 'package:flutter_devicelab/tasks/perf_tests.dart';
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android;
await task(DevToolsMemoryTest(
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
'test_driver/large_image_changer.dart',
).run);
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart';
import 'package:flutter_devicelab/tasks/perf_tests.dart';
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.ios;
await task(PerfTest(
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
'test_driver/large_image_changer.dart',
'large_image_changer',
measureCpuGpu: true,
).run);
}
...@@ -1125,11 +1125,15 @@ class DevToolsMemoryTest { ...@@ -1125,11 +1125,15 @@ class DevToolsMemoryTest {
.listen((String line) { .listen((String line) {
print('run stdout: $line'); print('run stdout: $line');
final RegExpMatch match = RegExp(r'An Observatory debugger and profiler on .+ is available at: ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)').firstMatch(line); final RegExpMatch match = RegExp(r'An Observatory debugger and profiler on .+ is available at: ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)').firstMatch(line);
if (match != null) { if (match != null && !observatoryUri.isCompleted) {
observatoryUri.complete(match[1]); observatoryUri.complete(match[1]);
_observatoryUri = match[1]; _observatoryUri = match[1];
} }
}, onDone: () { observatoryUri.complete(null); }); }, onDone: () {
if (!observatoryUri.isCompleted) {
observatoryUri.complete();
}
});
_forwardStream(_runProcess.stderr, 'run stderr'); _forwardStream(_runProcess.stderr, 'run stderr');
_observatoryUri = await observatoryUri.future; _observatoryUri = await observatoryUri.future;
......
...@@ -867,6 +867,20 @@ tasks: ...@@ -867,6 +867,20 @@ tasks:
stage: devicelab stage: devicelab
required_agent_capabilities: ["linux/android"] required_agent_capabilities: ["linux/android"]
large_image_changer_perf_android:
description: >
Measures memory usage when rotating through a series of large images.
stage: devicelab
required_agent_capabilities: ["linux/android"]
flaky: true
large_image_changer_perf_ios:
description: >
Measures memory, cpu, and gpu usage when rotating through a series of large images.
stage: devicelab
required_agent_capabilities: ["mac/ios"]
flaky: true
animated_placeholder_perf: animated_placeholder_perf:
description: > description: >
Measures frame build and rasterizer times, as well as frame build counts Measures frame build and rasterizer times, as well as frame build counts
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment