[dart2js] Defer deserialized CodegenResults by members.
For large applications only ~60% of these objects are used. This defers their deserializtion until they're accessed in the codegen member map.
In local testing on large applications this saved ~200MB of memory usage in the linker phase.
Change-Id: I8ff87803fc23ef2d3f954646687e3fc67b68a4f7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254600
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index e225449..da84cb3 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -28,6 +28,7 @@
import '../options.dart';
import '../util/sink_adapter.dart';
import '../world.dart';
+import 'deferrable.dart';
import 'serialization.dart';
/// A data class holding some data [T] and the associated [DataSourceIndices].
@@ -340,7 +341,7 @@
sink.writeMemberMap(
results,
(MemberEntity member, CodegenResult result) =>
- result.writeToDataSink(sink));
+ sink.writeDeferrable(() => result.writeToDataSink(sink)));
sink.close();
});
}
@@ -353,7 +354,7 @@
bool useDeferredSourceReads) async {
int shards = _options.codegenShards;
JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
- Map<MemberEntity, CodegenResult> results = {};
+ Map<MemberEntity, Deferrable<CodegenResult>> results = {};
for (int shard = 0; shard < shards; shard++) {
Uri uri = Uri.parse('${_options.readCodegenUri}$shard');
await measureIoSubtask('deserialize codegen', () async {
@@ -368,7 +369,7 @@
});
}
return DeserializedCodegenResults(
- globalTypeInferenceResults, codegenInputs, results);
+ globalTypeInferenceResults, codegenInputs, DeferrableValueMap(results));
}
void _deserializeCodegenInput(
@@ -377,7 +378,7 @@
Uri uri,
api.Input<List<int>> dataInput,
DataSourceIndices importedIndices,
- Map<MemberEntity, CodegenResult> results,
+ Map<MemberEntity, Deferrable<CodegenResult>> results,
bool useDeferredSourceReads) {
DataSourceReader source = DataSourceReader(
BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
@@ -386,17 +387,19 @@
importedIndices: importedIndices,
useDeferredStrategy: useDeferredSourceReads);
backendStrategy.prepareCodegenReader(source);
- Map<MemberEntity, CodegenResult> codegenResults =
+ Map<MemberEntity, Deferrable<CodegenResult>> codegenResults =
source.readMemberMap((MemberEntity member) {
- List<ModularName> modularNames = [];
- List<ModularExpression> modularExpressions = [];
- CodegenReader reader =
- CodegenReaderImpl(closedWorld, modularNames, modularExpressions);
- source.registerCodegenReader(reader);
- CodegenResult result = CodegenResult.readFromDataSource(
- source, modularNames, modularExpressions);
- source.deregisterCodegenReader(reader);
- return result;
+ return source.readDeferrable(() {
+ List<ModularName> modularNames = [];
+ List<ModularExpression> modularExpressions = [];
+ CodegenReader reader =
+ CodegenReaderImpl(closedWorld, modularNames, modularExpressions);
+ source.registerCodegenReader(reader);
+ CodegenResult result = CodegenResult.readFromDataSource(
+ source, modularNames, modularExpressions);
+ source.deregisterCodegenReader(reader);
+ return result;
+ });
});
_reporter.log('Read ${codegenResults.length} members from ${uri}');
results.addAll(codegenResults);