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/linked_element_factory.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart'; import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/summary2/reference.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:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
@ -106,7 +107,11 @@ class _Builder {
Reference.root(), Reference.root(),
); );
var linkResult = await link(elementFactory, inputLibraries); var linkResult = await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
performance: OperationPerformanceImpl('link'),
);
var bundleBuilder = PackageBundleBuilder(); var bundleBuilder = PackageBundleBuilder();
for (var library in inputLibraries) { 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/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro.dart'; import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart'; import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:path/src/context.dart'; import 'package:path/src/context.dart';
/// Context information necessary to analyze one or more libraries within an /// Context information necessary to analyze one or more libraries within an
@ -203,8 +204,12 @@ class LibraryContext {
LinkResult linkResult; LinkResult linkResult;
try { try {
linkResult = await link(elementFactory, inputLibraries, linkResult = await link2(
macroExecutor: macroExecutor); elementFactory: elementFactory,
performance: OperationPerformanceImpl('link'),
inputLibraries: inputLibraries,
macroExecutor: macroExecutor,
);
librariesLinked += cycle.libraries.length; librariesLinked += cycle.libraries.length;
} catch (exception, stackTrace) { } catch (exception, stackTrace) {
_throwLibraryCycleLinkException(cycle, exception, stackTrace); _throwLibraryCycleLinkException(cycle, exception, stackTrace);

View file

@ -916,7 +916,17 @@ class _LibraryContext {
} }
inputsTimer.stop(); 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; librariesLinked += cycle.libraries.length;
resolutionBytes = linkResult.resolutionBytes; 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/reference_resolver.dart';
import 'package:analyzer/src/summary2/scope.dart'; import 'package:analyzer/src/summary2/scope.dart';
import 'package:analyzer/src/summary2/types_builder.dart'; import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
class ImplicitEnumNodes { class ImplicitEnumNodes {
final EnumElementImpl element; final EnumElementImpl element;
@ -275,14 +276,30 @@ class LibraryBuilder {
]; ];
} }
Future<void> executeMacroTypesPhase() async { Future<void> executeMacroTypesPhase({
required OperationPerformanceImpl performance,
}) async {
final macroApplier = _macroApplier; final macroApplier = _macroApplier;
if (macroApplier == null) { if (macroApplier == null) {
return; return;
} }
await macroApplier.buildApplications(); await performance.runAsync(
var augmentationLibrary = await macroApplier.executeTypesPhase(); 'buildApplications',
(performance) async {
await macroApplier.buildApplications(
performance: performance,
);
},
);
final augmentationLibrary = await performance.runAsync(
'executeTypesPhase',
(performance) async {
return await macroApplier.executeTypesPhase();
},
);
if (augmentationLibrary == null) { if (augmentationLibrary == null) {
return; 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/type_alias.dart';
import 'package:analyzer/src/summary2/types_builder.dart'; import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/summary2/variance_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. /// Note that AST units and tokens of [inputLibraries] will be damaged.
@Deprecated('Use link2() instead')
Future<LinkResult> link( Future<LinkResult> link(
LinkedElementFactory elementFactory, LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries, { List<LinkInputLibrary> inputLibraries, {
macro.MultiMacroExecutor? macroExecutor, macro.MultiMacroExecutor? macroExecutor,
OperationPerformanceImpl? performance,
}) async { }) async {
var linker = Linker(elementFactory, macroExecutor); return await link2(
await linker.link(inputLibraries); 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( return LinkResult(
resolutionBytes: linker.resolutionBytes, resolutionBytes: linker.resolutionBytes,
macroGeneratedUnits: linker.macroGeneratedUnits, macroGeneratedUnits: linker.macroGeneratedUnits,
@ -79,12 +99,18 @@ class Linker {
return elementNodes[element]; 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) { for (var inputLibrary in inputLibraries) {
LibraryBuilder.build(this, inputLibrary); LibraryBuilder.build(this, inputLibrary);
} }
await _buildOutlines(); await _buildOutlines(
performance: performance,
);
_writeLibraries(); _writeLibraries();
} }
@ -94,13 +120,31 @@ class Linker {
} }
} }
Future<void> _buildOutlines() async { Future<void> _buildOutlines({
required OperationPerformanceImpl performance,
}) async {
_createTypeSystemIfNotLinkingDartCore(); _createTypeSystemIfNotLinkingDartCore();
await _computeLibraryScopes();
await performance.runAsync(
'computeLibraryScopes',
(performance) async {
await _computeLibraryScopes(
performance: performance,
);
},
);
_createTypeSystem(); _createTypeSystem();
_resolveTypes(); _resolveTypes();
_buildEnumChildren(); _buildEnumChildren();
await _executeMacroDeclarationsPhase();
await performance.runAsync(
'executeMacroDeclarationsPhase',
(_) async {
await _executeMacroDeclarationsPhase();
},
);
SuperConstructorResolver(this).perform(); SuperConstructorResolver(this).perform();
_performTopLevelInference(); _performTopLevelInference();
_resolveConstructors(); _resolveConstructors();
@ -117,14 +161,23 @@ class Linker {
} }
} }
Future<void> _computeLibraryScopes() async { Future<void> _computeLibraryScopes({
required OperationPerformanceImpl performance,
}) async {
for (var library in builders.values) { for (var library in builders.values) {
library.buildElements(); library.buildElements();
} }
for (var library in builders.values) { await performance.runAsync(
await library.executeMacroTypesPhase(); 'executeMacroTypesPhase',
} (performance) async {
for (var library in builders.values) {
await library.executeMacroTypesPhase(
performance: performance,
);
}
},
);
macroDeclarationBuilder.transferToElements(); 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/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart'; import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_declarations.dart'; import 'package:analyzer/src/summary2/macro_declarations.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
class LibraryMacroApplier { class LibraryMacroApplier {
final MultiMacroExecutor macroExecutor; final MultiMacroExecutor macroExecutor;
@ -47,7 +48,9 @@ class LibraryMacroApplier {
Linker get _linker => libraryBuilder.linker; Linker get _linker => libraryBuilder.linker;
/// Fill [_targets]s with macro applications. /// Fill [_targets]s with macro applications.
Future<void> buildApplications() async { Future<void> buildApplications({
required OperationPerformanceImpl performance,
}) async {
final collector = _MacroTargetElementCollector(); final collector = _MacroTargetElementCollector();
libraryBuilder.element.accept(collector); libraryBuilder.element.accept(collector);
@ -55,11 +58,17 @@ class LibraryMacroApplier {
final targetNode = _linker.elementNodes[targetElement]; final targetNode = _linker.elementNodes[targetElement];
// TODO(scheglov) support other declarations // TODO(scheglov) support other declarations
if (targetNode is ClassDeclaration) { if (targetNode is ClassDeclaration) {
await _buildApplications( await performance.runAsync(
targetElement, 'forClassDeclaration',
targetNode.metadata, (performance) async {
macro.DeclarationKind.clazz, await _buildApplications(
() => declarationBuilder.fromNode.classDeclaration(targetNode), targetElement,
targetNode.metadata,
macro.DeclarationKind.clazz,
() => declarationBuilder.fromNode.classDeclaration(targetNode),
performance: performance,
);
},
); );
} }
} }
@ -117,8 +126,9 @@ class LibraryMacroApplier {
MacroTargetElement targetElement, MacroTargetElement targetElement,
List<Annotation> annotations, List<Annotation> annotations,
macro.DeclarationKind declarationKind, macro.DeclarationKind declarationKind,
macro.DeclarationImpl Function() getDeclaration, macro.DeclarationImpl Function() getDeclaration, {
) async { required OperationPerformanceImpl performance,
}) async {
final applications = <_MacroApplication>[]; final applications = <_MacroApplication>[];
for (var i = 0; i < annotations.length; i++) { for (var i = 0; i < annotations.length; i++) {
@ -136,12 +146,14 @@ class LibraryMacroApplier {
annotationIndex: i, annotationIndex: i,
node: argumentsNode, node: argumentsNode,
); );
return await macroExecutor.instantiate( return await performance.runAsync('instantiate', (_) {
libraryUri: macroClass.librarySource.uri, return macroExecutor.instantiate(
className: macroClass.name, libraryUri: macroClass.librarySource.uri,
constructorName: constructorName, className: macroClass.name,
arguments: arguments, constructorName: constructorName,
); arguments: arguments,
);
});
}, },
annotationIndex: i, annotationIndex: i,
onError: (error) { 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 @override
OperationPerformanceImpl? getChild(String name) { OperationPerformanceImpl? getChild(String name) {
return _children.firstWhereOrNull( 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/summary2/reference.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.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:analyzer/src/util/uri.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:path/path.dart' as package_path; import 'package:path/path.dart' as package_path;
@ -103,7 +104,11 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
Reference.root(), Reference.root(),
); );
var sdkLinkResult = await link(elementFactory, inputLibraries); var sdkLinkResult = await link2(
elementFactory: elementFactory,
inputLibraries: inputLibraries,
performance: OperationPerformanceImpl('link'),
);
return _sdkBundle = _SdkBundle( return _sdkBundle = _SdkBundle(
resolutionBytes: sdkLinkResult.resolutionBytes, resolutionBytes: sdkLinkResult.resolutionBytes,
@ -128,75 +133,99 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
bool dumpSummaries = false, bool dumpSummaries = false,
List<Set<String>>? preBuildSequence, List<Set<String>>? preBuildSequence,
}) async { }) async {
_buildSourceFactory(); final performance = OperationPerformanceImpl('<root>');
final result = await performance.runAsync(
'buildLibrary',
(performance) async {
_buildSourceFactory();
var testFile = newFile(testFilePath, text); var testFile = newFile(testFilePath, text);
var testUri = sourceFactory.pathToUri(testFile.path)!; var testUri = sourceFactory.pathToUri(testFile.path)!;
var testSource = sourceFactory.forUri2(testUri)!; var testSource = sourceFactory.forUri2(testUri)!;
var inputLibraries = <LinkInputLibrary>[]; var inputLibraries = <LinkInputLibrary>[];
_addNonDartLibraries({}, inputLibraries, testSource); _addNonDartLibraries({}, inputLibraries, testSource);
var unitsInformativeBytes = <Uri, Uint8List>{}; var unitsInformativeBytes = <Uri, Uint8List>{};
for (var inputLibrary in inputLibraries) { for (var inputLibrary in inputLibraries) {
for (var inputUnit in inputLibrary.units) { for (var inputUnit in inputLibrary.units) {
var informativeBytes = writeUnitInformative(inputUnit.unit); var informativeBytes = writeUnitInformative(inputUnit.unit);
unitsInformativeBytes[inputUnit.uri] = informativeBytes; unitsInformativeBytes[inputUnit.uri] = informativeBytes;
} }
} }
var analysisContext = AnalysisContextImpl( var analysisContext = AnalysisContextImpl(
SynchronousSession( SynchronousSession(
AnalysisOptionsImpl()..contextFeatures = featureSet, AnalysisOptionsImpl()..contextFeatures = featureSet,
declaredVariables, declaredVariables,
), ),
sourceFactory, 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( // final performanceBuffer = StringBuffer();
analysisContext, // performance.children.single.write(buffer: performanceBuffer);
_AnalysisSessionForLinking(), // print(performanceBuffer);
Reference.root(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: {},
resolutionBytes: (await sdkBundle).resolutionBytes,
),
);
await _linkConfiguredLibraries( return result;
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');
} }
@mustCallSuper @mustCallSuper
@ -366,6 +395,7 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
LinkedElementFactory elementFactory, LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries, List<LinkInputLibrary> inputLibraries,
List<Set<String>>? uriStrSetList, List<Set<String>>? uriStrSetList,
OperationPerformanceImpl performance,
) async { ) async {
if (uriStrSetList == null) { if (uriStrSetList == null) {
return; return;
@ -381,13 +411,19 @@ abstract class ElementsBaseTest with ResourceProviderMixin {
} }
} }
await link( await performance.runAsync('link', (performance) async {
elementFactory, await link2(
cycleInputLibraries, elementFactory: elementFactory,
macroExecutor: _macroExecutor, 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. // Remove libraries that we just linked.
cycleInputLibraries.forEach(inputLibraries.remove); cycleInputLibraries.forEach(inputLibraries.remove);