Unverified Commit ec58182b authored by James D. Lin's avatar James D. Lin Committed by GitHub

[flutter tools] Make SizeAnalyzer support .apk files that don't use libapp.so (#63250)

parent 25de9419
...@@ -17,11 +17,14 @@ class SizeAnalyzer { ...@@ -17,11 +17,14 @@ class SizeAnalyzer {
@required this.fileSystem, @required this.fileSystem,
@required this.logger, @required this.logger,
@required this.processUtils, @required this.processUtils,
this.appFilenamePattern = 'libapp.so',
}); });
final FileSystem fileSystem; final FileSystem fileSystem;
final Logger logger; final Logger logger;
final ProcessUtils processUtils; final ProcessUtils processUtils;
final Pattern appFilenamePattern;
String _appFilename;
static const String aotSnapshotFileName = 'aot-snapshot.json'; static const String aotSnapshotFileName = 'aot-snapshot.json';
...@@ -29,7 +32,7 @@ class SizeAnalyzer { ...@@ -29,7 +32,7 @@ class SizeAnalyzer {
/// Analyzes [apk] and [aotSnapshot] to output a [Map] object that includes /// Analyzes [apk] and [aotSnapshot] to output a [Map] object that includes
/// the breakdown of the both files, where the breakdown of [aotSnapshot] is placed /// the breakdown of the both files, where the breakdown of [aotSnapshot] is placed
/// under 'lib/arm64-v8a/libapp.so'. /// under 'lib/arm64-v8a/$_appFilename'.
/// ///
/// The [aotSnapshot] can be either instruction sizes snapshot or v8 snapshot. /// The [aotSnapshot] can be either instruction sizes snapshot or v8 snapshot.
Future<Map<String, dynamic>> analyzeApkSizeAndAotSnapshot({ Future<Map<String, dynamic>> analyzeApkSizeAndAotSnapshot({
...@@ -78,7 +81,7 @@ class SizeAnalyzer { ...@@ -78,7 +81,7 @@ class SizeAnalyzer {
byteSize: firstLevelPath.byteSize, byteSize: firstLevelPath.byteSize,
level: 1, level: 1,
); );
// Print the expansion of lib directory to show more info for libapp.so. // Print the expansion of lib directory to show more info for `appFilename`.
if (firstLevelPath.name == 'lib') { if (firstLevelPath.name == 'lib') {
_printLibChildrenPaths(firstLevelPath, '', aotSnapshotJsonRoot); _printLibChildrenPaths(firstLevelPath, '', aotSnapshotJsonRoot);
} }
...@@ -91,9 +94,10 @@ class SizeAnalyzer { ...@@ -91,9 +94,10 @@ class SizeAnalyzer {
apkAnalysisJson['type'] = 'apk'; apkAnalysisJson['type'] = 'apk';
// TODO(peterdjlee): Add aot snapshot for all platforms. // TODO(peterdjlee): Add aot snapshot for all platforms.
assert(_appFilename != null);
apkAnalysisJson = _addAotSnapshotDataToApkAnalysis( apkAnalysisJson = _addAotSnapshotDataToApkAnalysis(
apkAnalysisJson: apkAnalysisJson, apkAnalysisJson: apkAnalysisJson,
path: 'lib/arm64-v8a/libapp.so (Dart AOT)'.split('/'), // Pass in a list of paths by splitting with '/'. path: 'lib/arm64-v8a/$_appFilename (Dart AOT)'.split('/'), // Pass in a list of paths by splitting with '/'.
aotSnapshotJson: processedAotSnapshotJson, aotSnapshotJson: processedAotSnapshotJson,
); );
...@@ -137,9 +141,10 @@ class SizeAnalyzer { ...@@ -137,9 +141,10 @@ class SizeAnalyzer {
if (childWithPathAsName == null) { if (childWithPathAsName == null) {
childWithPathAsName = _SymbolNode(path); childWithPathAsName = _SymbolNode(path);
if (path.endsWith('libapp.so')) { if (matchesPattern(path, pattern: appFilenamePattern) != null) {
_appFilename = path;
childWithPathAsName.name += ' (Dart AOT)'; childWithPathAsName.name += ' (Dart AOT)';
} else if (path.endsWith('libflutter.so')) { } else if (path == 'libflutter.so') {
childWithPathAsName.name += ' (Flutter Engine)'; childWithPathAsName.name += ' (Flutter Engine)';
} }
currentNode.addChild(childWithPathAsName); currentNode.addChild(childWithPathAsName);
...@@ -155,7 +160,7 @@ class SizeAnalyzer { ...@@ -155,7 +160,7 @@ class SizeAnalyzer {
/// Prints all children paths for the lib/ directory in an APK. /// Prints all children paths for the lib/ directory in an APK.
/// ///
/// A brief summary of aot snapshot is printed under 'lib/arm64-v8a/libapp.so'. /// A brief summary of aot snapshot is printed under 'lib/arm64-v8a/$_appFilename'.
void _printLibChildrenPaths( void _printLibChildrenPaths(
_SymbolNode currentNode, _SymbolNode currentNode,
String totalPath, String totalPath,
...@@ -163,7 +168,9 @@ class SizeAnalyzer { ...@@ -163,7 +168,9 @@ class SizeAnalyzer {
) { ) {
totalPath += currentNode.name; totalPath += currentNode.name;
if (currentNode.children.isNotEmpty && !currentNode.name.contains('libapp.so')) { assert(_appFilename != null);
if (currentNode.children.isNotEmpty
&& currentNode.name != '$_appFilename (Dart AOT)') {
for (final _SymbolNode child in currentNode.children) { for (final _SymbolNode child in currentNode.children) {
_printLibChildrenPaths(child, '$totalPath/', aotSnapshotJsonRoot); _printLibChildrenPaths(child, '$totalPath/', aotSnapshotJsonRoot);
} }
...@@ -172,8 +179,8 @@ class SizeAnalyzer { ...@@ -172,8 +179,8 @@ class SizeAnalyzer {
_printEntitySize(totalPath, byteSize: currentNode.byteSize, level: 2); _printEntitySize(totalPath, byteSize: currentNode.byteSize, level: 2);
// We picked this file because arm64-v8a is likely the most popular // We picked this file because arm64-v8a is likely the most popular
// architecture. ther architecture sizes should be similar. // architecture. Other architecture sizes should be similar.
const String libappPath = 'lib/arm64-v8a/libapp.so'; final String libappPath = 'lib/arm64-v8a/$_appFilename';
// TODO(peterdjlee): Analyze aot size for all platforms. // TODO(peterdjlee): Analyze aot size for all platforms.
if (totalPath.contains(libappPath)) { if (totalPath.contains(libappPath)) {
_printAotSnapshotSummary(aotSnapshotJsonRoot); _printAotSnapshotSummary(aotSnapshotJsonRoot);
...@@ -368,3 +375,10 @@ class _SymbolNode { ...@@ -368,3 +375,10 @@ class _SymbolNode {
return json; return json;
} }
} }
/// Matches `pattern` against the entirety of `string`.
@visibleForTesting
Match matchesPattern(String string, {@required Pattern pattern}) {
final Match match = pattern.matchAsPrefix(string);
return (match != null && match.end == string.length) ? match : null;
}
...@@ -602,8 +602,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -602,8 +602,8 @@ abstract class FlutterCommand extends Command<void> {
argParser.addFlag( argParser.addFlag(
FlutterOptions.kAnalyzeSize, FlutterOptions.kAnalyzeSize,
defaultsTo: false, defaultsTo: false,
help: 'Whether to produce additonal profile information for artifact output size. ' help: 'Whether to produce additional profile information for artifact output size. '
'This flag is only support on release builds on macOS/Linux hosts.' 'This flag is only supported on release builds on macOS/Linux hosts.'
); );
} }
......
...@@ -26,7 +26,7 @@ Length Method Size Cmpr Date Time CRC-32 Name ...@@ -26,7 +26,7 @@ Length Method Size Cmpr Date Time CRC-32 Name
11708 Defl:N 2592 78% 00-00-1980 00:00 07733eef AndroidManifest.xml 11708 Defl:N 2592 78% 00-00-1980 00:00 07733eef AndroidManifest.xml
1399 Defl:N 1092 22% 00-00-1980 00:00 f53d952a META-INF/CERT.RSA 1399 Defl:N 1092 22% 00-00-1980 00:00 f53d952a META-INF/CERT.RSA
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 META-INF/CERT.SF 46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 META-INF/CERT.SF
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libapp.so 46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libxyzzyapp.so
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libflutter.so 46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libflutter.so
''', ''',
); );
...@@ -70,6 +70,17 @@ void main() { ...@@ -70,6 +70,17 @@ void main() {
processManager = FakeProcessManager.list(<FakeCommand>[unzipCommmand]); processManager = FakeProcessManager.list(<FakeCommand>[unzipCommmand]);
}); });
test('matchesPattern matches only entire strings', () {
expect(matchesPattern('', pattern: ''), isNotNull);
expect(matchesPattern('', pattern: 'foo'), null);
expect(matchesPattern('foo', pattern: ''), null);
expect(matchesPattern('foo', pattern: 'foo'), isNotNull);
expect(matchesPattern('foo', pattern: 'foobar'), null);
expect(matchesPattern('foobar', pattern: 'foo'), null);
expect(matchesPattern('foobar', pattern: RegExp(r'.*b.*')), isNotNull);
expect(matchesPattern('foobar', pattern: RegExp(r'.*b')), null);
});
test('builds APK analysis correctly', () async { test('builds APK analysis correctly', () async {
final SizeAnalyzer sizeAnalyzer = SizeAnalyzer( final SizeAnalyzer sizeAnalyzer = SizeAnalyzer(
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -78,6 +89,7 @@ void main() { ...@@ -78,6 +89,7 @@ void main() {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
), ),
appFilenamePattern: RegExp(r'lib.*app\.so'),
); );
final File apk = fileSystem.file('test.apk')..createSync(); final File apk = fileSystem.file('test.apk')..createSync();
...@@ -109,7 +121,7 @@ void main() { ...@@ -109,7 +121,7 @@ void main() {
expect(arm64Map['n'], equals('arm64-v8a')); expect(arm64Map['n'], equals('arm64-v8a'));
expect(arm64Map['value'], equals(29060)); expect(arm64Map['value'], equals(29060));
final Map<String, dynamic> libAppMap = arm64Map['children'][0] as Map<String, dynamic>; final Map<String, dynamic> libAppMap = arm64Map['children'][0] as Map<String, dynamic>;
expect(libAppMap['n'], equals('libapp.so (Dart AOT)')); expect(libAppMap['n'], equals('libxyzzyapp.so (Dart AOT)'));
expect(libAppMap['value'], equals(14530)); expect(libAppMap['value'], equals(14530));
expect(libAppMap['children'].length, equals(3)); expect(libAppMap['children'].length, equals(3));
final Map<String, dynamic> internalMap = libAppMap['children'][0] as Map<String, dynamic>; final Map<String, dynamic> internalMap = libAppMap['children'][0] as Map<String, dynamic>;
...@@ -140,6 +152,7 @@ void main() { ...@@ -140,6 +152,7 @@ void main() {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
), ),
appFilenamePattern: RegExp(r'lib.*app\.so'),
); );
final File apk = fileSystem.file('test.apk')..createSync(); final File apk = fileSystem.file('test.apk')..createSync();
...@@ -155,7 +168,7 @@ void main() { ...@@ -155,7 +168,7 @@ void main() {
' AndroidManifest.xml 3 KB', ' AndroidManifest.xml 3 KB',
' META-INF 15 KB', ' META-INF 15 KB',
' lib 28 KB', ' lib 28 KB',
' lib/arm64-v8a/libapp.so (Dart AOT) 14 KB', ' lib/arm64-v8a/libxyzzyapp.so (Dart AOT) 14 KB',
' Dart AOT symbols accounted decompressed size 14 KB', ' Dart AOT symbols accounted decompressed size 14 KB',
' dart:_internal/SubListIterable 6 KB', ' dart:_internal/SubListIterable 6 KB',
' @stubs/allocation-stubs/dart:core/ArgumentError 5 KB', ' @stubs/allocation-stubs/dart:core/ArgumentError 5 KB',
......
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