Thread OperationPerformance through link() and macro applications.

So, I can see the performance statistics during tests, but in the
future it could be possible to connect it to the analysis operations
tree.

Change-Id: I56ee80e92427f53471e062824467f8572341a851
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244185
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-05-10 16:15:13 +00:00 committed by Commit Bot
parent 3c01efcbb0
commit c40fe123f9
8 changed files with 245 additions and 101 deletions

View file

@ -22,6 +22,7 @@ import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
@ -106,7 +107,11 @@ class _Builder {
Reference.root(),
);
var linkResult = await link(elementFactory, inputLibraries);
var linkResult = await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
performance: OperationPerformanceImpl('link'),
);
var bundleBuilder = PackageBundleBuilder();
for (var library in inputLibraries) {

View file

@ -26,6 +26,7 @@ import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:path/src/context.dart';
/// Context information necessary to analyze one or more libraries within an
@ -203,8 +204,12 @@ class LibraryContext {
LinkResult linkResult;
try {
linkResult = await link(elementFactory, inputLibraries,
macroExecutor: macroExecutor);
linkResult = await link2(
elementFactory: elementFactory,
performance: OperationPerformanceImpl('link'),
inputLibraries: inputLibraries,
macroExecutor: macroExecutor,
);
librariesLinked += cycle.libraries.length;
} catch (exception, stackTrace) {
_throwLibraryCycleLinkException(cycle, exception, stackTrace);

View file

@ -916,7 +916,17 @@ class _LibraryContext {
}
inputsTimer.stop();
var linkResult = await link(elementFactory, inputLibraries);
var linkResult = await performance.runAsync(
'link',
(performance) async {
return await link2(
elementFactory: elementFactory,
performance: performance,
inputLibraries: inputLibraries,
);
},
);
librariesLinked += cycle.libraries.length;
resolutionBytes = linkResult.resolutionBytes;

View file

@ -24,6 +24,7 @@ import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/reference_resolver.dart';
import 'package:analyzer/src/summary2/scope.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
class ImplicitEnumNodes {
final EnumElementImpl element;
@ -275,14 +276,30 @@ class LibraryBuilder {
];
}
Future<void> executeMacroTypesPhase() async {
Future<void> executeMacroTypesPhase({
required OperationPerformanceImpl performance,
}) async {
final macroApplier = _macroApplier;
if (macroApplier == null) {
return;
}
await macroApplier.buildApplications();
var augmentationLibrary = await macroApplier.executeTypesPhase();
await performance.runAsync(
'buildApplications',
(performance) async {
await macroApplier.buildApplications(
performance: performance,
);
},
);
final augmentationLibrary = await performance.runAsync(
'executeTypesPhase',
(performance) async {
return await macroApplier.executeTypesPhase();
},
);
if (augmentationLibrary == null) {
return;
}

View file

@ -25,15 +25,35 @@ import 'package:analyzer/src/summary2/top_level_inference.dart';
import 'package:analyzer/src/summary2/type_alias.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/summary2/variance_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
/// Note that AST units and tokens of [inputLibraries] will be damaged.
@Deprecated('Use link2() instead')
Future<LinkResult> link(
LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries, {
macro.MultiMacroExecutor? macroExecutor,
OperationPerformanceImpl? performance,
}) async {
var linker = Linker(elementFactory, macroExecutor);
await linker.link(inputLibraries);
return await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
performance: OperationPerformanceImpl('<root>'),
);
}
/// Note that AST units and tokens of [inputLibraries] will be damaged.
Future<LinkResult> link2({
required LinkedElementFactory elementFactory,
required OperationPerformanceImpl performance,
required List<LinkInputLibrary> inputLibraries,
macro.MultiMacroExecutor? macroExecutor,
}) async {
final linker = Linker(elementFactory, macroExecutor);
await linker.link(
performance: performance,
inputLibraries: inputLibraries,
);
return LinkResult(
resolutionBytes: linker.resolutionBytes,
macroGeneratedUnits: linker.macroGeneratedUnits,
@ -79,12 +99,18 @@ class Linker {
return elementNodes[element];
}
Future<void> link(List<LinkInputLibrary> inputLibraries) async {
Future<void> link({
required OperationPerformanceImpl performance,
required List<LinkInputLibrary> inputLibraries,
}) async {
for (var inputLibrary in inputLibraries) {
LibraryBuilder.build(this, inputLibrary);
}
await _buildOutlines();
await _buildOutlines(
performance: performance,
);
_writeLibraries();
}
@ -94,13 +120,31 @@ class Linker {
}
}
Future<void> _buildOutlines() async {
Future<void> _buildOutlines({
required OperationPerformanceImpl performance,
}) async {
_createTypeSystemIfNotLinkingDartCore();
await _computeLibraryScopes();
await performance.runAsync(
'computeLibraryScopes',
(performance) async {
await _computeLibraryScopes(
performance: performance,
);
},
);
_createTypeSystem();
_resolveTypes();
_buildEnumChildren();
await _executeMacroDeclarationsPhase();
await performance.runAsync(
'executeMacroDeclarationsPhase',
(_) async {
await _executeMacroDeclarationsPhase();
},
);
SuperConstructorResolver(this).perform();
_performTopLevelInference();
_resolveConstructors();
@ -117,14 +161,23 @@ class Linker {
}
}
Future<void> _computeLibraryScopes() async {
Future<void> _computeLibraryScopes({
required OperationPerformanceImpl performance,
}) async {
for (var library in builders.values) {
library.buildElements();
}
for (var library in builders.values) {
await library.executeMacroTypesPhase();
}
await performance.runAsync(
'executeMacroTypesPhase',
(performance) async {
for (var library in builders.values) {
await library.executeMacroTypesPhase(
performance: performance,
);
}
},
);
macroDeclarationBuilder.transferToElements();

View file

@ -20,6 +20,7 @@ import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_declarations.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
class LibraryMacroApplier {
final MultiMacroExecutor macroExecutor;
@ -47,7 +48,9 @@ class LibraryMacroApplier {
Linker get _linker => libraryBuilder.linker;
/// Fill [_targets]s with macro applications.
Future<void> buildApplications() async {
Future<void> buildApplications({
required OperationPerformanceImpl performance,
}) async {
final collector = _MacroTargetElementCollector();
libraryBuilder.element.accept(collector);
@ -55,11 +58,17 @@ class LibraryMacroApplier {
final targetNode = _linker.elementNodes[targetElement];
// TODO(scheglov) support other declarations
if (targetNode is ClassDeclaration) {
await _buildApplications(
targetElement,
targetNode.metadata,
macro.DeclarationKind.clazz,
() => declarationBuilder.fromNode.classDeclaration(targetNode),
await performance.runAsync(
'forClassDeclaration',
(performance) async {
await _buildApplications(
targetElement,
targetNode.metadata,
macro.DeclarationKind.clazz,
() => declarationBuilder.fromNode.classDeclaration(targetNode),
performance: performance,
);
},
);
}
}
@ -117,8 +126,9 @@ class LibraryMacroApplier {
MacroTargetElement targetElement,
List<Annotation> annotations,
macro.DeclarationKind declarationKind,
macro.DeclarationImpl Function() getDeclaration,
) async {
macro.DeclarationImpl Function() getDeclaration, {
required OperationPerformanceImpl performance,
}) async {
final applications = <_MacroApplication>[];
for (var i = 0; i < annotations.length; i++) {
@ -136,12 +146,14 @@ class LibraryMacroApplier {
annotationIndex: i,
node: argumentsNode,
);
return await macroExecutor.instantiate(
libraryUri: macroClass.librarySource.uri,
className: macroClass.name,
constructorName: constructorName,
arguments: arguments,
);
return await performance.runAsync('instantiate', (_) {
return macroExecutor.instantiate(
libraryUri: macroClass.librarySource.uri,
className: macroClass.name,
constructorName: constructorName,
arguments: arguments,
);
});
},
annotationIndex: i,
onError: (error) {

View file

@ -105,6 +105,12 @@ class OperationPerformanceImpl implements OperationPerformance {
);
}
/// Collapse any children into this operation, making [elapsedSelf] equal
/// to [elapsed].
void collapse() {
_children.clear();
}
@override
OperationPerformanceImpl? getChild(String name) {
return _children.firstWhereOrNull(

View file

@ -31,6 +31,7 @@ import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/util/uri.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as package_path;
@ -103,7 +104,11 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
Reference.root(),
);
var sdkLinkResult = await link(elementFactory, inputLibraries);
var sdkLinkResult = await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
performance: OperationPerformanceImpl('link'),
);
return _sdkBundle = _SdkBundle(
resolutionBytes: sdkLinkResult.resolutionBytes,
@ -128,75 +133,99 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
bool dumpSummaries = false,
List<Set<String>>? preBuildSequence,
}) async {
_buildSourceFactory();
final performance = OperationPerformanceImpl('<root>');
final result = await performance.runAsync(
'buildLibrary',
(performance) async {
_buildSourceFactory();
var testFile = newFile(testFilePath, text);
var testUri = sourceFactory.pathToUri(testFile.path)!;
var testSource = sourceFactory.forUri2(testUri)!;
var testFile = newFile(testFilePath, text);
var testUri = sourceFactory.pathToUri(testFile.path)!;
var testSource = sourceFactory.forUri2(testUri)!;
var inputLibraries = <LinkInputLibrary>[];
_addNonDartLibraries({}, inputLibraries, testSource);
var inputLibraries = <LinkInputLibrary>[];
_addNonDartLibraries({}, inputLibraries, testSource);
var unitsInformativeBytes = <Uri, Uint8List>{};
for (var inputLibrary in inputLibraries) {
for (var inputUnit in inputLibrary.units) {
var informativeBytes = writeUnitInformative(inputUnit.unit);
unitsInformativeBytes[inputUnit.uri] = informativeBytes;
}
}
var unitsInformativeBytes = <Uri, Uint8List>{};
for (var inputLibrary in inputLibraries) {
for (var inputUnit in inputLibrary.units) {
var informativeBytes = writeUnitInformative(inputUnit.unit);
unitsInformativeBytes[inputUnit.uri] = informativeBytes;
}
}
var analysisContext = AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl()..contextFeatures = featureSet,
declaredVariables,
),
sourceFactory,
var analysisContext = AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl()..contextFeatures = featureSet,
declaredVariables,
),
sourceFactory,
);
var elementFactory = LinkedElementFactory(
analysisContext,
_AnalysisSessionForLinking(),
Reference.root(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: {},
resolutionBytes: (await sdkBundle).resolutionBytes,
),
);
await performance.runAsync(
'linkConfiguredLibraries',
(performance) async {
await _linkConfiguredLibraries(
elementFactory,
inputLibraries,
preBuildSequence,
performance,
);
},
);
var linkResult = await performance.runAsync(
'link',
(performance) async {
return await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
macroExecutor: _macroExecutor,
performance: performance,
);
},
);
for (var macroUnit in linkResult.macroGeneratedUnits) {
var informativeBytes = writeUnitInformative(macroUnit.unit);
unitsInformativeBytes[macroUnit.uri] = informativeBytes;
}
if (!keepLinkingLibraries) {
elementFactory.removeBundle(
inputLibraries.map((e) => e.uriStr).toSet(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: unitsInformativeBytes,
resolutionBytes: linkResult.resolutionBytes,
),
);
}
return elementFactory.libraryOfUri2('$testUri');
},
);
var elementFactory = LinkedElementFactory(
analysisContext,
_AnalysisSessionForLinking(),
Reference.root(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: {},
resolutionBytes: (await sdkBundle).resolutionBytes,
),
);
// final performanceBuffer = StringBuffer();
// performance.children.single.write(buffer: performanceBuffer);
// print(performanceBuffer);
await _linkConfiguredLibraries(
elementFactory,
inputLibraries,
preBuildSequence,
);
var linkResult = await link(
elementFactory,
inputLibraries,
macroExecutor: _macroExecutor,
);
for (var macroUnit in linkResult.macroGeneratedUnits) {
var informativeBytes = writeUnitInformative(macroUnit.unit);
unitsInformativeBytes[macroUnit.uri] = informativeBytes;
}
if (!keepLinkingLibraries) {
elementFactory.removeBundle(
inputLibraries.map((e) => e.uriStr).toSet(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: unitsInformativeBytes,
resolutionBytes: linkResult.resolutionBytes,
),
);
}
return elementFactory.libraryOfUri2('$testUri');
return result;
}
@mustCallSuper
@ -366,6 +395,7 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries,
List<Set<String>>? uriStrSetList,
OperationPerformanceImpl performance,
) async {
if (uriStrSetList == null) {
return;
@ -381,13 +411,19 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
}
}
await link(
elementFactory,
cycleInputLibraries,
macroExecutor: _macroExecutor,
);
await performance.runAsync('link', (performance) async {
await link2(
elementFactory: elementFactory,
inputLibraries: cycleInputLibraries,
macroExecutor: _macroExecutor,
performance: performance,
);
performance.collapse();
});
await _buildMacroLibraries(elementFactory, macroLibraries);
await performance.runAsync('buildMacroLibraries', (_) async {
await _buildMacroLibraries(elementFactory, macroLibraries);
});
// Remove libraries that we just linked.
cycleInputLibraries.forEach(inputLibraries.remove);