blob: bf711a7efdb6da444026d3c9fd3d6dc892c73390 [file] [log] [blame]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Generate a json file representing the files in the Dart SDK and their sizes.
/// Print out instructions for opening Dart DevTools to visualize this info.
library;
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
late final String dartSdkPath;
final List<FileStats> fileStats = [];
void main(List<String> arguments) {
final vm = Platform.resolvedExecutable;
dartSdkPath = p.dirname(p.dirname(vm));
final version =
File(p.join(dartSdkPath, 'version')).readAsStringSync().trim();
final sdkData = build(Directory(dartSdkPath), extra: {
'comment-1': 'Dart SDK $version',
'comment-2': '<size>',
'type': 'web',
});
final sdkSize = fileStats.fold<int>(0, (previous, e) => previous + e.size);
sdkData['comment-2'] = sizeMB(sdkSize);
final outFile = File('sdk-size.json');
outFile.writeAsStringSync(JsonEncoder.withIndent('').convert(sdkData));
const width = 52;
print('Large SDK files');
print('-----------------');
fileStats.sort();
for (var stat in fileStats) {
if (stat.size < 2 * 1042 * 1024) break;
print('${stat.path.padRight(width)}: ${sizeMB(stat.size)}');
}
print('');
print('SDK: $dartSdkPath');
print('Version: $version');
print('Size: ${sizeMB(sdkSize)}');
print('');
print('Wrote data to ${outFile.path}; to view the SDK size treemap, run:');
print('');
print(' dart devtools --app-size-base=${outFile.path}');
print('');
}
String sizeMB(int size) => '${(size / (1024.0 * 1024)).toStringAsFixed(1)}MB';
Map build(FileSystemEntity entity, {Map<String, String> extra = const {}}) {
const fsBlockSize = 4096.0;
if (entity is File) {
final size =
((entity.lengthSync() / fsBlockSize).ceilToDouble() * fsBlockSize)
.truncate();
fileStats.add(FileStats(p.relative(entity.path, from: dartSdkPath), size));
return {
'n': entity.name,
'value': size,
};
} else {
entity as Directory;
return {
...extra,
'n': '${entity.name}/',
'children': [
...entity.listSyncSorted().map(build),
],
};
}
}
extension FileSystemEntityExtension on FileSystemEntity {
String get name => p.basename(path);
}
extension DirectoryExtension on Directory {
List<FileSystemEntity> listSyncSorted() {
return listSync()..sort((a, b) => a.name.compareTo(b.name));
}
}
class FileStats implements Comparable<FileStats> {
final String path;
final int size;
FileStats(this.path, this.size);
@override
int compareTo(FileStats other) => other.size - size;
}