Skip to content

Commit 6d4ebea

Browse files
jensjohaCommit Queue
authored andcommitted
[kernel] Optimize reading of metadata further
This optimization is based on the assumption (which at least holds true for the dill file extracted from the mentioned bug) that only very few nodes actually have metadata associated with it. For the test file, more than two million node-offsets is looked up, and only ~7.5 thousand nodes actually have metadata on it. What is done here is to assume that most often we ask offsets in order and that most often the answer is that there's no metadata (when we fall into this case we can return `false` quickly) and we can skip looking up the actual metadata. This furthermore - although not benchmark here - should make it (a lot) faster in the case where we have multiple subsections as we here only lookup in in one index. Only upon a `true` response from that we have to lookup in all subsections to find and read the actual metadata to associate. Reading the test file without metadata, taking an average of averages (average of 5 runs of the binary benchmarks output for "AstFromBinaryEager") takes: 374481.4 us. Before https://dart-review.googlesource.com/c/sdk/+/391761 reading the test file with metadata takes: 627120.68 us. This was about a quarter of a second, or 67+% slower. With https://dart-review.googlesource.com/c/sdk/+/391761 this number became: 441784.44 us. A reduction of ~185 ms, or almost 30%, making the tax of reading metadata "only" ~18%. With this CL this number goes to 398011.44 us. This is a further reduction of ~43 ms, or almost 10% (for a combined reduction of ~230 ms or 36+%). The tax of reading metadata is now ~6.3%. Bug: flutter/flutter#156713 Change-Id: I20bbabecfc8976293fe897528d05fc2145e2a8c0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392021 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Jens Johansen <[email protected]>
1 parent 01dddf6 commit 6d4ebea

File tree

2 files changed

+87
-26
lines changed

2 files changed

+87
-26
lines changed

pkg/kernel/lib/binary/ast_from_binary.dart

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4162,6 +4162,8 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
41624162
/// List of metadata subsections that have corresponding [MetadataRepository]
41634163
/// and are awaiting to be parsed and attached to nodes.
41644164
List<_MetadataSubsection>? _subsections;
4165+
List<int>? _allKnownMetadataKeys;
4166+
int? _previousMetadataLookupKey;
41654167

41664168
BinaryBuilderWithMetadata(List<int> bytes,
41674169
{String? filename,
@@ -4180,6 +4182,7 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
41804182
// If reading a component with several sub-components there's no reason to
41814183
// lookup in old ones.
41824184
_subsections = null;
4185+
_allKnownMetadataKeys = null;
41834186

41844187
// At the beginning of this function _byteOffset points right past
41854188
// metadataMappings to string table.
@@ -4204,11 +4207,13 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
42044207
// Read nodeOffsetToMetadataOffset mapping.
42054208
final Map<int, int> mapping = <int, int>{};
42064209
_byteOffset = mappingStart;
4210+
List<int> allKnownMetadataKeys = _allKnownMetadataKeys ??= [];
42074211
for (int j = 0; j < mappingLength; j++) {
42084212
final int nodeOffset = _componentStartOffset + readUint32();
42094213
final int metadataOffset =
42104214
binaryOffsetForMetadataPayloads + readUint32();
42114215
mapping[nodeOffset] = metadataOffset;
4216+
allKnownMetadataKeys.add(nodeOffset);
42124217
}
42134218

42144219
(_subsections ??= <_MetadataSubsection>[])
@@ -4218,6 +4223,7 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
42184223
// Start of the subsection and the end of the previous one.
42194224
endOffset = mappingStart - 4;
42204225
}
4226+
_allKnownMetadataKeys?.sort();
42214227
}
42224228

42234229
Object _readMetadata(Node node, MetadataRepository repository, int offset) {
@@ -4230,12 +4236,47 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
42304236
return metadata;
42314237
}
42324238

4239+
bool _hasMetadata(int nodeOffset) {
4240+
List<int>? allKnownMetadataKeys = _allKnownMetadataKeys;
4241+
if (allKnownMetadataKeys == null) return false;
4242+
if (allKnownMetadataKeys.isEmpty) return false;
4243+
4244+
int? prevIndex = _previousMetadataLookupKey;
4245+
if (prevIndex != null) {
4246+
if (prevIndex >= 0 && prevIndex < allKnownMetadataKeys.length - 1) {
4247+
int prevOffset = allKnownMetadataKeys[prevIndex];
4248+
int nextOffset = allKnownMetadataKeys[prevIndex + 1];
4249+
if (prevOffset < nodeOffset && nextOffset > nodeOffset) {
4250+
// Common case: This is between the previously found metadata
4251+
// and the next metadata (and doesn't itself have metadata).
4252+
return false;
4253+
}
4254+
}
4255+
}
4256+
4257+
_previousMetadataLookupKey = null;
4258+
int low = 0, high = allKnownMetadataKeys.length - 1;
4259+
while (low < high) {
4260+
int mid = high - ((high - low) >> 1); // Get middle, rounding up.
4261+
int pivot = allKnownMetadataKeys[mid];
4262+
if (pivot <= nodeOffset) {
4263+
low = mid;
4264+
} else {
4265+
high = mid - 1;
4266+
}
4267+
}
4268+
this._previousMetadataLookupKey = low;
4269+
if (allKnownMetadataKeys[low] == nodeOffset) {
4270+
return true;
4271+
}
4272+
return false;
4273+
}
4274+
42334275
@override
42344276
T _associateMetadata<T extends Node>(T node, int nodeOffset) {
42354277
if (_subsections == null) {
42364278
return node;
42374279
}
4238-
42394280
for (_MetadataSubsection subsection in _subsections!) {
42404281
// First check if there is any metadata associated with this node.
42414282
final int? metadataOffset = subsection.mapping[nodeOffset];
@@ -4251,137 +4292,156 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
42514292
@override
42524293
DartType readDartType({bool forSupertype = false}) {
42534294
final int nodeOffset = _byteOffset;
4295+
final bool hasMetadata = _hasMetadata(_byteOffset);
42544296
final DartType result = super.readDartType(forSupertype: forSupertype);
4255-
return _associateMetadata(result, nodeOffset);
4297+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42564298
}
42574299

42584300
@override
42594301
Library readLibrary(Component component, int endOffset) {
42604302
final int nodeOffset = _byteOffset;
4303+
final bool hasMetadata = _hasMetadata(_byteOffset);
42614304
final Library result = super.readLibrary(component, endOffset);
4262-
return _associateMetadata(result, nodeOffset);
4305+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42634306
}
42644307

42654308
@override
42664309
Typedef readTypedef() {
42674310
final int nodeOffset = _byteOffset;
4311+
final bool hasMetadata = _hasMetadata(_byteOffset);
42684312
final Typedef result = super.readTypedef();
4269-
return _associateMetadata(result, nodeOffset);
4313+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42704314
}
42714315

42724316
@override
42734317
Class readClass(int endOffset) {
42744318
final int nodeOffset = _byteOffset;
4319+
final bool hasMetadata = _hasMetadata(_byteOffset);
42754320
final Class result = super.readClass(endOffset);
4276-
return _associateMetadata(result, nodeOffset);
4321+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42774322
}
42784323

42794324
@override
42804325
Extension readExtension() {
42814326
final int nodeOffset = _byteOffset;
4327+
final bool hasMetadata = _hasMetadata(_byteOffset);
42824328
final Extension result = super.readExtension();
4283-
return _associateMetadata(result, nodeOffset);
4329+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42844330
}
42854331

42864332
@override
42874333
ExtensionTypeDeclaration readExtensionTypeDeclaration() {
42884334
final int nodeOffset = _byteOffset;
4335+
final bool hasMetadata = _hasMetadata(_byteOffset);
42894336
final ExtensionTypeDeclaration result =
42904337
super.readExtensionTypeDeclaration();
4291-
return _associateMetadata(result, nodeOffset);
4338+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42924339
}
42934340

42944341
@override
42954342
Field readField() {
42964343
final int nodeOffset = _byteOffset;
4344+
final bool hasMetadata = _hasMetadata(_byteOffset);
42974345
final Field result = super.readField();
4298-
return _associateMetadata(result, nodeOffset);
4346+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
42994347
}
43004348

43014349
@override
43024350
Constructor readConstructor() {
43034351
final int nodeOffset = _byteOffset;
4352+
final bool hasMetadata = _hasMetadata(_byteOffset);
43044353
final Constructor result = super.readConstructor();
4305-
return _associateMetadata(result, nodeOffset);
4354+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43064355
}
43074356

43084357
@override
43094358
Procedure readProcedure(int endOffset) {
43104359
final int nodeOffset = _byteOffset;
4360+
final bool hasMetadata = _hasMetadata(_byteOffset);
43114361
final Procedure result = super.readProcedure(endOffset);
4312-
return _associateMetadata(result, nodeOffset);
4362+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43134363
}
43144364

43154365
@override
43164366
Initializer readInitializer() {
43174367
final int nodeOffset = _byteOffset;
4368+
final bool hasMetadata = _hasMetadata(_byteOffset);
43184369
final Initializer result = super.readInitializer();
4319-
return _associateMetadata(result, nodeOffset);
4370+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43204371
}
43214372

43224373
@override
43234374
FunctionNode readFunctionNode(
43244375
{bool lazyLoadBody = false, int outerEndOffset = -1}) {
43254376
final int nodeOffset = _byteOffset;
4377+
final bool hasMetadata = _hasMetadata(_byteOffset);
43264378
final FunctionNode result = super.readFunctionNode(
43274379
lazyLoadBody: lazyLoadBody, outerEndOffset: outerEndOffset);
4328-
return _associateMetadata(result, nodeOffset);
4380+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43294381
}
43304382

43314383
@override
43324384
Expression readExpression() {
43334385
final int nodeOffset = _byteOffset;
4386+
final bool hasMetadata = _hasMetadata(_byteOffset);
43344387
final Expression result = super.readExpression();
4335-
return _associateMetadata(result, nodeOffset);
4388+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43364389
}
43374390

43384391
@override
43394392
Arguments readArguments() {
43404393
final int nodeOffset = _byteOffset;
4394+
final bool hasMetadata = _hasMetadata(_byteOffset);
43414395
final Arguments result = super.readArguments();
4342-
return _associateMetadata(result, nodeOffset);
4396+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43434397
}
43444398

43454399
@override
43464400
NamedExpression readNamedExpression() {
43474401
final int nodeOffset = _byteOffset;
4402+
final bool hasMetadata = _hasMetadata(_byteOffset);
43484403
final NamedExpression result = super.readNamedExpression();
4349-
return _associateMetadata(result, nodeOffset);
4404+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43504405
}
43514406

43524407
@override
43534408
VariableDeclaration readVariableDeclaration() {
43544409
final int nodeOffset = _byteOffset;
4410+
final bool hasMetadata = _hasMetadata(_byteOffset);
43554411
final VariableDeclaration result = super.readVariableDeclaration();
4356-
return _associateMetadata(result, nodeOffset);
4412+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43574413
}
43584414

43594415
@override
43604416
Statement readStatement() {
43614417
final int nodeOffset = _byteOffset;
4418+
final bool hasMetadata = _hasMetadata(_byteOffset);
43624419
final Statement result = super.readStatement();
4363-
return _associateMetadata(result, nodeOffset);
4420+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43644421
}
43654422

43664423
@override
43674424
Combinator readCombinator() {
43684425
final int nodeOffset = _byteOffset;
4426+
final bool hasMetadata = _hasMetadata(_byteOffset);
43694427
final Combinator result = super.readCombinator();
4370-
return _associateMetadata(result, nodeOffset);
4428+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43714429
}
43724430

43734431
@override
43744432
LibraryDependency readLibraryDependency() {
43754433
final int nodeOffset = _byteOffset;
4434+
final bool hasMetadata = _hasMetadata(_byteOffset);
43764435
final LibraryDependency result = super.readLibraryDependency();
4377-
return _associateMetadata(result, nodeOffset);
4436+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43784437
}
43794438

43804439
@override
43814440
LibraryPart readLibraryPart() {
43824441
final int nodeOffset = _byteOffset;
4442+
final bool hasMetadata = _hasMetadata(_byteOffset);
43834443
final LibraryPart result = super.readLibraryPart();
4384-
return _associateMetadata(result, nodeOffset);
4444+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
43854445
}
43864446

43874447
@override
@@ -4399,18 +4459,20 @@ class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
43994459
@override
44004460
Supertype readSupertype() {
44014461
final int nodeOffset = _byteOffset;
4462+
final bool hasMetadata = _hasMetadata(_byteOffset);
44024463
InterfaceType type =
44034464
super.readDartType(forSupertype: true) as InterfaceType;
4404-
return _associateMetadata(
4405-
new Supertype.byReference(type.classReference, type.typeArguments),
4406-
nodeOffset);
4465+
Supertype result =
4466+
new Supertype.byReference(type.classReference, type.typeArguments);
4467+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
44074468
}
44084469

44094470
@override
44104471
Name readName() {
44114472
final int nodeOffset = _byteOffset;
4473+
final bool hasMetadata = _hasMetadata(_byteOffset);
44124474
final Name result = super.readName();
4413-
return _associateMetadata(result, nodeOffset);
4475+
return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
44144476
}
44154477
}
44164478

pkg/kernel/test/binary_bench2.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,7 @@ Component _fromBinary(List<int> bytes,
201201
filename: 'filename', disableLazyReading: eager);
202202
builder.readComponent(component);
203203
if (verbose) {
204-
// print("#lookups: ${builder.lookups}");
205-
// print("#good lookups: ${builder.goodLookups}");
204+
// No current verbose output.
206205
}
207206
} else {
208207
new BinaryBuilder(bytes, filename: 'filename', disableLazyReading: eager)

0 commit comments

Comments
 (0)