mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 16:37:43 +00:00
[dart2js] Fix resource usage of binary to json converter tool.
Improves binary -> json conversion from >900s to ~52s for a large program. This change contains 2 major fixes: 1) Make element name deduping be O(1) rather than O(n) by using a hash map. I didn't calculate how many duplicated names there were but this change improved the runtime of the conversion process by ~10x. 2) Use chunked string writing for the json encoding/file writing process. By doing chunked conversion with buffered writes we avoid having the entire JSON blob in memory and fewer midsized write operations end up being faster. Without this the program took ~87s for the same large program. Change-Id: I2d3cddbbb96895b68086fce2256937d567beff11 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345940 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
parent
c46b63d2c7
commit
06adfb8d6b
|
@ -51,7 +51,33 @@ class ToJsonCommand extends Command<void> with PrintUsageException {
|
|||
var json = AllInfoJsonCodec(isBackwardCompatible: isBackwardCompatible)
|
||||
.encode(info);
|
||||
String outputFilename = args['out'] ?? '$filename.json';
|
||||
File(outputFilename)
|
||||
.writeAsStringSync(const JsonEncoder.withIndent(" ").convert(json));
|
||||
final sink = File(outputFilename).openWrite();
|
||||
final converterSink = const JsonEncoder.withIndent(" ")
|
||||
.startChunkedConversion(_BufferedStringOutputSink(sink));
|
||||
converterSink.add(json);
|
||||
converterSink.close();
|
||||
await sink.close();
|
||||
}
|
||||
}
|
||||
|
||||
class _BufferedStringOutputSink implements Sink<String> {
|
||||
StringBuffer buffer = StringBuffer();
|
||||
final StringSink outputSink;
|
||||
static const int _maxLength = 1024 * 1024 * 500;
|
||||
|
||||
_BufferedStringOutputSink(this.outputSink);
|
||||
|
||||
@override
|
||||
void add(String data) {
|
||||
buffer.write(data);
|
||||
if (buffer.length > _maxLength) {
|
||||
outputSink.write(buffer.toString());
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void close() {
|
||||
outputSink.write(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
|
|||
final bool isBackwardCompatible;
|
||||
|
||||
final Map<Info, Id> ids = HashMap<Info, Id>();
|
||||
final Set<String> usedIds = <String>{};
|
||||
final Map<String, int> idCounter = <String, int>{};
|
||||
|
||||
AllInfoToJsonConverter({this.isBackwardCompatible = false});
|
||||
|
||||
|
@ -373,14 +373,10 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
|
|||
name = longName(info, useLibraryUri: true, forId: true);
|
||||
}
|
||||
|
||||
Id id = Id(info.kind, name);
|
||||
// longName isn't guaranteed to create unique serializedIds for some info
|
||||
// constructs (such as closures), so we disambiguate here.
|
||||
int count = 0;
|
||||
while (!usedIds.add(id.serializedId)) {
|
||||
id = Id(info.kind, '$name%${count++}');
|
||||
}
|
||||
|
||||
final count = idCounter.update(name, (v) => v + 1, ifAbsent: () => 0);
|
||||
final id = Id(info.kind, count == 0 ? name : '$name%$count');
|
||||
return ids[info] = id;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue