Unverified Commit 52661bc7 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] skip copying 1GB of data from chrome cache dirs (#81170)

* [flutter_tools] skip copying 1GB of data from chrome cache dirs

* Update chrome.dart
parent b74df388
...@@ -107,10 +107,12 @@ String getDisplayPath(String fullPath, FileSystem fileSystem) { ...@@ -107,10 +107,12 @@ String getDisplayPath(String fullPath, FileSystem fileSystem) {
/// source/destination file pair. /// source/destination file pair.
/// ///
/// Skips files if [shouldCopyFile] returns `false`. /// Skips files if [shouldCopyFile] returns `false`.
/// Does not recurse over directories if [shouldCopyDirectory] returns `false`.
void copyDirectory( void copyDirectory(
Directory srcDir, Directory srcDir,
Directory destDir, { Directory destDir, {
bool Function(File srcFile, File destFile)? shouldCopyFile, bool Function(File srcFile, File destFile)? shouldCopyFile,
bool Function(Directory)? shouldCopyDirectory,
void Function(File srcFile, File destFile)? onFileCopied, void Function(File srcFile, File destFile)? onFileCopied,
}) { }) {
if (!srcDir.existsSync()) { if (!srcDir.existsSync()) {
...@@ -134,6 +136,9 @@ void copyDirectory( ...@@ -134,6 +136,9 @@ void copyDirectory(
newFile.writeAsBytesSync(entity.readAsBytesSync()); newFile.writeAsBytesSync(entity.readAsBytesSync());
onFileCopied?.call(entity, newFile); onFileCopied?.call(entity, newFile);
} else if (entity is Directory) { } else if (entity is Directory) {
if (shouldCopyDirectory != null && !shouldCopyDirectory(entity)) {
continue;
}
copyDirectory( copyDirectory(
entity, entity,
destDir.fileSystem.directory(newPath), destDir.fileSystem.directory(newPath),
......
...@@ -318,13 +318,24 @@ class ChromiumLauncher { ...@@ -318,13 +318,24 @@ class ChromiumLauncher {
/// ///
/// Note: more detailed docs of the Chrome user preferences store exists here: /// Note: more detailed docs of the Chrome user preferences store exists here:
/// https://www.chromium.org/developers/design-documents/preferences. /// https://www.chromium.org/developers/design-documents/preferences.
///
/// This intentionally skips the Cache, Code Cache, and GPUCache directories.
/// While we're not sure exactly what is in them, this constitutes nearly 1 GB
/// of data for a fresh flutter run and adds significant overhead to all startups.
/// For workflows that may require this data, using the start-paused flag and
/// dart debug extension with a user controlled browser profile will lead to a
/// better experience.
void _cacheUserSessionInformation(Directory userDataDir, Directory cacheDir) { void _cacheUserSessionInformation(Directory userDataDir, Directory cacheDir) {
final Directory targetChromeDefault = _fileSystem.directory(_fileSystem.path.join(cacheDir.path, _chromeDefaultPath)); final Directory targetChromeDefault = _fileSystem.directory(_fileSystem.path.join(cacheDir.path, _chromeDefaultPath));
final Directory sourceChromeDefault = _fileSystem.directory(_fileSystem.path.join(userDataDir.path, _chromeDefaultPath)); final Directory sourceChromeDefault = _fileSystem.directory(_fileSystem.path.join(userDataDir.path, _chromeDefaultPath));
if (sourceChromeDefault.existsSync()) { if (sourceChromeDefault.existsSync()) {
targetChromeDefault.createSync(recursive: true); targetChromeDefault.createSync(recursive: true);
try { try {
copyDirectory(sourceChromeDefault, targetChromeDefault); copyDirectory(
sourceChromeDefault,
targetChromeDefault,
shouldCopyDirectory: _isNotCacheDirectory
);
} on FileSystemException catch (err) { } on FileSystemException catch (err) {
// This is a best-effort update. Display the message in case the failure is relevant. // This is a best-effort update. Display the message in case the failure is relevant.
// one possible example is a file lock due to multiple running chrome instances. // one possible example is a file lock due to multiple running chrome instances.
...@@ -352,13 +363,24 @@ class ChromiumLauncher { ...@@ -352,13 +363,24 @@ class ChromiumLauncher {
try { try {
if (sourceChromeDefault.existsSync()) { if (sourceChromeDefault.existsSync()) {
targetChromeDefault.createSync(recursive: true); targetChromeDefault.createSync(recursive: true);
copyDirectory(sourceChromeDefault, targetChromeDefault); copyDirectory(
sourceChromeDefault,
targetChromeDefault,
shouldCopyDirectory: _isNotCacheDirectory,
);
} }
} on FileSystemException catch (err) { } on FileSystemException catch (err) {
_logger.printError('Failed to restore Chrome preferences: $err'); _logger.printError('Failed to restore Chrome preferences: $err');
} }
} }
// Cache, Code Cache, and GPUCache are nearly 1GB of data
bool _isNotCacheDirectory(Directory directory) {
return !directory.path.endsWith('Cache') &&
!directory.path.endsWith('Code Cache') &&
!directory.path.endsWith('GPUCache');
}
Future<Chromium> _connect(Chromium chrome, bool skipCheck) async { Future<Chromium> _connect(Chromium chrome, bool skipCheck) async {
// The connection is lazy. Try a simple call to make sure the provided // The connection is lazy. Try a simple call to make sure the provided
// connection is valid. // connection is valid.
......
...@@ -6,6 +6,7 @@ import 'dart:async'; ...@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:io' as io; import 'dart:io' as io;
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
...@@ -99,6 +100,25 @@ void main() { ...@@ -99,6 +100,25 @@ void main() {
expect(destination.childFile('a.txt').existsSync(), isFalse); expect(destination.childFile('a.txt').existsSync(), isFalse);
expect(destination.childDirectory('nested').childFile('a.txt').existsSync(), isFalse); expect(destination.childDirectory('nested').childFile('a.txt').existsSync(), isFalse);
}); });
testWithoutContext('Skip directories if shouldCopyDirectory returns false', () {
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final Directory origin = fileSystem.directory('/origin');
origin.createSync();
fileSystem.file(fileSystem.path.join('origin', 'a.txt')).writeAsStringSync('irrelevant');
fileSystem.directory('/origin/nested').createSync();
fileSystem.file(fileSystem.path.join('origin', 'nested', 'a.txt')).writeAsStringSync('irrelevant');
fileSystem.file(fileSystem.path.join('origin', 'nested', 'b.txt')).writeAsStringSync('irrelevant');
final Directory destination = fileSystem.directory('/destination');
copyDirectory(origin, destination, shouldCopyDirectory: (Directory directory) {
return !directory.path.endsWith('nested');
});
expect(destination, exists);
expect(destination.childDirectory('nested'), isNot(exists));
expect(destination.childDirectory('nested').childFile('b.txt'),isNot(exists));
});
}); });
group('escapePath', () { group('escapePath', () {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:async'; import 'dart:async';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
...@@ -26,6 +27,12 @@ const List<String> kChromeArgs = <String>[ ...@@ -26,6 +27,12 @@ const List<String> kChromeArgs = <String>[
'--disable-translate', '--disable-translate',
]; ];
const List<String> kCodeCache = <String>[
'Cache',
'Code Cache',
'GPUCache',
];
const String kDevtoolsStderr = '\n\nDevTools listening\n\n'; const String kDevtoolsStderr = '\n\nDevTools listening\n\n';
void main() { void main() {
...@@ -351,7 +358,7 @@ void main() { ...@@ -351,7 +358,7 @@ void main() {
); );
}); });
testWithoutContext('can seed chrome temp directory with existing session data', () async { testWithoutContext('can seed chrome temp directory with existing session data, excluding Cache folder', () async {
final Completer<void> exitCompleter = Completer<void>.sync(); final Completer<void> exitCompleter = Completer<void>.sync();
final Directory dataDir = fileSystem.directory('chrome-stuff'); final Directory dataDir = fileSystem.directory('chrome-stuff');
final File preferencesFile = dataDir final File preferencesFile = dataDir
...@@ -362,9 +369,16 @@ void main() { ...@@ -362,9 +369,16 @@ void main() {
..writeAsStringSync('"exit_type":"Crashed"'); ..writeAsStringSync('"exit_type":"Crashed"');
final Directory defaultContentDirectory = dataDir final Directory defaultContentDirectory = dataDir
.childDirectory('Default')
.childDirectory('Foo');
defaultContentDirectory.createSync(recursive: true);
// Create Cache directories that should be skipped
for (final String cache in kCodeCache) {
dataDir
.childDirectory('Default') .childDirectory('Default')
.childDirectory('Foo'); .childDirectory(cache)
defaultContentDirectory.createSync(recursive: true); .createSync(recursive: true);
}
processManager.addCommand(FakeCommand( processManager.addCommand(FakeCommand(
command: const <String>[ command: const <String>[
...@@ -397,7 +411,15 @@ void main() { ...@@ -397,7 +411,15 @@ void main() {
.childDirectory('Default') .childDirectory('Default')
.childDirectory('Foo'); .childDirectory('Foo');
expect(defaultContentDir.existsSync(), true); expect(defaultContentDir, exists);
// Validate cache dirs are not copied.
for (final String cache in kCodeCache) {
expect(fileSystem
.directory('.tmp_rand0/flutter_tools_chrome_device.rand0')
.childDirectory('Default')
.childDirectory(cache), isNot(exists));
}
}); });
testWithoutContext('can retry launch when glibc bug happens', () async { testWithoutContext('can retry launch when glibc bug happens', () async {
......
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