Unverified Commit 090fc5cc authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tools] Use gzip level 1 for devfs transfer compression (#54123)

parent fa35698e
......@@ -61,6 +61,7 @@ export 'dart:io'
// File, NO! Use `file_system.dart`
// FileSystemEntity, NO! Use `file_system.dart`
gzip,
GZipCodec,
HandshakeException,
HttpClient,
HttpClientRequest,
......
......@@ -52,6 +52,9 @@ abstract class OperatingSystemUtils {
processManager: processManager,
);
@visibleForTesting
static final GZipCodec gzipLevel1 = GZipCodec(level: 1);
final FileSystem _fileSystem;
final Logger _logger;
final Platform _platform;
......@@ -98,6 +101,11 @@ abstract class OperatingSystemUtils {
/// Returns true if the gzip is not corrupt (does not check tar).
bool verifyGzip(File gzippedFile);
/// Compresses a stream using gzip level 1 (faster but larger).
Stream<List<int>> gzipLevel1Stream(Stream<List<int>> stream) {
return stream.cast<List<int>>().transform<List<int>>(gzipLevel1.encoder);
}
/// Returns a pretty name string for the current operating system.
///
/// If available, the detailed version of the OS is included.
......
......@@ -12,6 +12,7 @@ import 'base/context.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/net.dart';
import 'base/os.dart';
import 'build_info.dart';
import 'bundle.dart';
import 'compile.dart';
......@@ -46,8 +47,10 @@ abstract class DevFSContent {
Stream<List<int>> contentsAsStream();
Stream<List<int>> contentsAsCompressedStream() {
return contentsAsStream().cast<List<int>>().transform<List<int>>(gzip.encoder);
Stream<List<int>> contentsAsCompressedStream(
OperatingSystemUtils osUtils,
) {
return osUtils.gzipLevel1Stream(contentsAsStream());
}
/// Return the list of files this content depends on.
......@@ -265,15 +268,21 @@ class DevFSException implements Exception {
}
class _DevFSHttpWriter {
_DevFSHttpWriter(this.fsName, VMService serviceProtocol)
_DevFSHttpWriter(
this.fsName,
VMService serviceProtocol, {
@required OperatingSystemUtils osUtils,
})
: httpAddress = serviceProtocol.httpAddress,
_client = (context.get<HttpClientFactory>() == null)
? HttpClient()
: context.get<HttpClientFactory>()();
: context.get<HttpClientFactory>()(),
_osUtils = osUtils;
final String fsName;
final Uri httpAddress;
final HttpClient _client;
final OperatingSystemUtils _osUtils;
static const int kMaxInFlight = 6;
......@@ -312,7 +321,9 @@ class _DevFSHttpWriter {
request.headers.removeAll(HttpHeaders.acceptEncodingHeader);
request.headers.add('dev_fs_name', fsName);
request.headers.add('dev_fs_uri_b64', base64.encode(utf8.encode('$deviceUri')));
final Stream<List<int>> contents = content.contentsAsCompressedStream();
final Stream<List<int>> contents = content.contentsAsCompressedStream(
_osUtils,
);
await request.addStream(contents);
final HttpClientResponse response = await request.close();
response.listen((_) => null,
......@@ -385,8 +396,13 @@ class DevFS {
this.fsName,
this.rootDirectory, {
String packagesFilePath,
@required OperatingSystemUtils osUtils,
}) : _operations = ServiceProtocolDevFSOperations(serviceProtocol),
_httpWriter = _DevFSHttpWriter(fsName, serviceProtocol),
_httpWriter = _DevFSHttpWriter(
fsName,
serviceProtocol,
osUtils: osUtils,
),
_packagesFilePath = packagesFilePath ?? globals.fs.path.join(rootDirectory.path, kPackagesFileName);
DevFS.operations(
......
......@@ -281,6 +281,7 @@ class FlutterDevice {
fsName,
rootDirectory,
packagesFilePath: packagesFilePath,
osUtils: globals.os,
);
return devFS.create();
}
......
......@@ -86,6 +86,10 @@ void main() {
expect(result[1].path, kPath2);
});
});
testWithoutContext('stream compression level', () {
expect(OperatingSystemUtils.gzipLevel1.level, equals(1));
});
}
class MockProcessManager extends Mock implements ProcessManager {}
......@@ -11,6 +11,7 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/vmservice.dart';
......@@ -96,6 +97,7 @@ void main() {
group('mocked http client', () {
HttpOverrides savedHttpOverrides;
HttpClient httpClient;
OperatingSystemUtils osUtils;
setUpAll(() {
tempDir = _newTempDir(fs);
......@@ -103,6 +105,7 @@ void main() {
savedHttpOverrides = HttpOverrides.current;
httpClient = MockOddlyFailingHttpClient();
HttpOverrides.global = MyHttpOverrides(httpClient);
osUtils = MockOperatingSystemUtils();
});
tearDownAll(() async {
......@@ -147,7 +150,12 @@ void main() {
return Future<HttpClientResponse>.value(httpClientResponse);
});
final DevFS devFS = DevFS(vmService, 'test', tempDir);
final DevFS devFS = DevFS(
vmService,
'test',
tempDir,
osUtils: osUtils,
);
await devFS.create();
final MockResidentCompiler residentCompiler = MockResidentCompiler();
......@@ -163,6 +171,7 @@ void main() {
expect(report.success, isTrue);
verify(httpClient.putUrl(any)).called(kFailedAttempts + 1);
verify(httpRequest.close()).called(kFailedAttempts + 1);
verify(osUtils.gzipLevel1Stream(any)).called(kFailedAttempts + 1);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
HttpClientFactory: () => () => httpClient,
......@@ -185,7 +194,12 @@ void main() {
setUp(() {
vmService.resetState();
devFS = DevFS(vmService, 'test', tempDir);
devFS = DevFS(
vmService,
'test',
tempDir,
osUtils: FakeOperatingSystemUtils(),
);
});
tearDownAll(() async {
......@@ -477,3 +491,4 @@ class MockOddlyFailingHttpClient extends Mock implements HttpClient {}
class MockHttpClientRequest extends Mock implements HttpClientRequest {}
class MockHttpHeaders extends Mock implements HttpHeaders {}
class MockHttpClientResponse extends Mock implements HttpClientResponse {}
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
......@@ -321,6 +321,9 @@ class FakeOperatingSystemUtils implements OperatingSystemUtils {
@override
bool verifyGzip(File gzippedFile) => true;
@override
Stream<List<int>> gzipLevel1Stream(Stream<List<int>> stream) => stream;
@override
String get name => 'fake OS name and version';
......
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