[analyzer] Faster export scope calculation in bad cases
With the `big_chain_benchmark` for ImportExportCycle and ImportCycleExportChain it scales a lot better. The other ones (ImportCycle, ImportChain, ImportExportChain) doesn't change. For ImportExportCycle, in AOT mode, before we got: ``` +------+-----------+------------+------------+ | Size | Initial | Completion | Fully done | +------+-----------+------------+------------+ | 16 | 0.46673 | 0.169486 | 0.406448 | | 32 | 0.875871 | 0.242876 | 0.85543 | | 64 | 1.583077 | 0.465915 | 1.506953 | | 128 | 3.198071 | 0.903894 | 3.09165 | | 256 | 6.786677 | 2.149489 | 6.779569 | | 512 | 17.346131 | 8.92149 | 17.971033 | | 1024 | 63.358453 | 46.152089 | 65.401559 | +------+-----------+------------+------------+ ``` now instead we get: ``` +------+-----------+------------+------------+ | Size | Initial | Completion | Fully done | +------+-----------+------------+------------+ | 16 | 0.474942 | 0.166857 | 0.411457 | | 32 | 0.834925 | 0.243397 | 0.76843 | | 64 | 1.608813 | 0.439885 | 1.53438 | | 128 | 3.198453 | 0.805756 | 3.302559 | | 256 | 6.347211 | 1.712426 | 6.165624 | | 512 | 12.874747 | 3.551489 | 13.1461 | | 1024 | 27.14403 | 7.844261 | 27.32785 | +------+-----------+------------+------------+ ``` An almost 6x improvement for completion and 2x+ improvement for both initial analysis and analysing after the change. For ImportCycleExportChain, in AOT mode, before we got: ``` +------+-----------+------------+------------+ | Size | Initial | Completion | Fully done | +------+-----------+------------+------------+ | 16 | 0.454349 | 0.152505 | 0.400889 | | 32 | 0.892146 | 0.302407 | 0.81263 | | 64 | 1.67604 | 0.439954 | 1.517379 | | 128 | 3.335087 | 0.907002 | 3.262481 | | 256 | 6.378526 | 1.943725 | 6.292922 | | 512 | 15.477861 | 6.461358 | 15.560008 | | 1024 | 50.671197 | 33.14349 | 51.689455 | +------+-----------+------------+------------+ ``` now instead we get: ``` +------+-----------+------------+------------+ | Size | Initial | Completion | Fully done | +------+-----------+------------+------------+ | 16 | 0.548357 | 0.166257 | 0.415632 | | 32 | 0.906483 | 0.296618 | 0.910544 | | 64 | 1.623723 | 0.464061 | 1.527888 | | 128 | 3.067769 | 0.801507 | 2.927981 | | 256 | 6.224551 | 1.596711 | 6.098531 | | 512 | 12.941757 | 3.277487 | 12.345753 | | 1024 | 25.870713 | 7.020787 | 25.760605 | +------+-----------+------------+------------+ ``` A ~4.7x improvement on completion and ~2x improvement for both initial analysis and analysing after the change. Change-Id: I052879c1695ad5f0aa63c2d96013a1e3eae96428 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/413421 Reviewed-by: Lasse Nielsen <lrn@google.com> Commit-Queue: Jens Johansen <jensj@google.com>
This commit is contained in:
committed by
Commit Queue
parent
06d938046f
commit
d3bbacfa9d
@@ -61,6 +61,7 @@ class ExportedReferenceExported extends ExportedReference {
|
||||
});
|
||||
|
||||
void addLocation(ExportLocation location) {
|
||||
// This list is very small, contains on it is probably ok.
|
||||
if (!locations.contains(location)) {
|
||||
locations.add(location);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:analyzer/src/dart/element/name_union.dart';
|
||||
import 'package:analyzer/src/fine/library_manifest.dart';
|
||||
import 'package:analyzer/src/summary2/bundle_writer.dart';
|
||||
import 'package:analyzer/src/summary2/detach_nodes.dart';
|
||||
import 'package:analyzer/src/summary2/export.dart';
|
||||
import 'package:analyzer/src/summary2/library_builder.dart';
|
||||
import 'package:analyzer/src/summary2/linked_element_factory.dart';
|
||||
import 'package:analyzer/src/summary2/reference.dart';
|
||||
@@ -179,19 +180,47 @@ class Linker {
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var hasChanges = false;
|
||||
// We keep a queue of exports to propagate.
|
||||
// First we loop over every reference that both exports and is exported,
|
||||
// but then we only process the exports that should be propagated.
|
||||
var additionalExportData = <_AdditionalExport>[];
|
||||
|
||||
void addExport(Export export, String name, ExportedReference reference) {
|
||||
if (export.addToExportScope(name, reference)) {
|
||||
// We've added [name] to [export.exporter]s export scope.
|
||||
// We need to propagate that to anyone that exports that library.
|
||||
additionalExportData
|
||||
.add(_AdditionalExport(export.exporter, name, reference));
|
||||
}
|
||||
}
|
||||
|
||||
for (var exported in both) {
|
||||
for (var export in exported.exports) {
|
||||
exported.exportScope.forEach((name, reference) {
|
||||
addExport(export, name, reference);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
while (additionalExportData.isNotEmpty) {
|
||||
var data = additionalExportData.removeLast();
|
||||
for (var export in data.exported.exports) {
|
||||
addExport(export, data.name, data.reference);
|
||||
}
|
||||
}
|
||||
|
||||
assert(() {
|
||||
for (var exported in both) {
|
||||
for (var export in exported.exports) {
|
||||
exported.exportScope.forEach((name, reference) {
|
||||
if (export.addToExportScope(name, reference)) {
|
||||
hasChanges = true;
|
||||
throw "Error in export calculation: Assert failed.";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!hasChanges) break;
|
||||
}
|
||||
return true;
|
||||
}(), true);
|
||||
|
||||
for (var library in builders.values) {
|
||||
library.storeExportScope();
|
||||
@@ -362,3 +391,11 @@ class LinkResult {
|
||||
required this.resolutionBytes,
|
||||
});
|
||||
}
|
||||
|
||||
class _AdditionalExport {
|
||||
final LibraryBuilder exported;
|
||||
final String name;
|
||||
final ExportedReference reference;
|
||||
|
||||
_AdditionalExport(this.exported, this.name, this.reference);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_helper_2.dart";
|
||||
export "bigger_cyclic_helper_2.dart";
|
||||
|
||||
void get2(int i) {
|
||||
print("2: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_helper_3.dart";
|
||||
export "bigger_cyclic_helper_3.dart";
|
||||
|
||||
void get3(int i) {
|
||||
print("3: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_helper_4.dart";
|
||||
export "bigger_cyclic_helper_4.dart";
|
||||
|
||||
void get4(int i) {
|
||||
print("4: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_helper_5.dart";
|
||||
export "bigger_cyclic_helper_5.dart";
|
||||
|
||||
void get5(int i) {
|
||||
print("5: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_test.dart";
|
||||
export "bigger_cyclic_test.dart";
|
||||
|
||||
void get6(int i) {
|
||||
print("6: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "bigger_cyclic_helper_1.dart";
|
||||
export "bigger_cyclic_helper_1.dart";
|
||||
|
||||
void main() {
|
||||
get1(1);
|
||||
}
|
||||
|
||||
void get1(int i) {
|
||||
print("1: $i");
|
||||
if (i > 0) {
|
||||
get1(i - 1);
|
||||
get2(i - 1);
|
||||
get3(i - 1);
|
||||
get4(i - 1);
|
||||
get5(i - 1);
|
||||
get6(i - 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user