| // Coverage-ignore(suite): Not run. | |
| // Copyright (c) 2022, 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. | |
| class Benchmarker { | |
| final List<PhaseTiming> _phaseTimings = new List<PhaseTiming>.generate( | |
| BenchmarkPhases.values.length, | |
| (index) { | |
| assert(BenchmarkPhases.values[index].index == index); | |
| return new PhaseTiming(BenchmarkPhases.values[index]); | |
| }, | |
| growable: false, | |
| ); | |
| final Stopwatch _totalStopwatch = new Stopwatch()..start(); | |
| final Stopwatch _phaseStopwatch = new Stopwatch()..start(); | |
| final Stopwatch _subdivideStopwatch = new Stopwatch()..start(); | |
| BenchmarkPhases _currentPhase = BenchmarkPhases.implicitInitialization; | |
| List<BenchmarkSubdivides> _subdivides = [ | |
| BenchmarkSubdivides.subdividesUnaccountedFor, | |
| ]; | |
| void reset() { | |
| _totalStopwatch.start(); | |
| _totalStopwatch.reset(); | |
| _phaseStopwatch.start(); | |
| _phaseStopwatch.reset(); | |
| _subdivideStopwatch.start(); | |
| _subdivideStopwatch.reset(); | |
| for (int i = 0; i < _phaseTimings.length; i++) { | |
| assert(BenchmarkPhases.values[i].index == i); | |
| _phaseTimings[i] = new PhaseTiming(BenchmarkPhases.values[i]); | |
| } | |
| _subdivides = [BenchmarkSubdivides.subdividesUnaccountedFor]; | |
| _currentPhase = BenchmarkPhases.implicitInitialization; | |
| } | |
| void beginSubdivide(BenchmarkSubdivides phase) { | |
| _pauseLatestSubdivide(addAsCount: false); | |
| _subdivideStopwatch.reset(); | |
| _subdivides.add(phase); | |
| } | |
| void _pauseLatestSubdivide({required bool addAsCount}) { | |
| if (_subdivides.isEmpty) return; | |
| BenchmarkSubdivides subdivide = _subdivides.last; | |
| _phaseTimings[_currentPhase.index].subdivides[subdivide.index].addRuntime( | |
| _subdivideStopwatch.elapsedMicroseconds, | |
| addAsCount: addAsCount, | |
| ); | |
| } | |
| void endSubdivide() { | |
| if (_subdivides.isEmpty) throw "Can't end a nonexistent subdivide"; | |
| _pauseLatestSubdivide(addAsCount: true); | |
| _subdivides.removeLast(); | |
| _subdivideStopwatch.reset(); | |
| } | |
| void enterPhase(BenchmarkPhases phase) { | |
| if (_currentPhase == phase) return; | |
| if (_subdivides.isEmpty) { | |
| throw "System subdivide removed."; | |
| } | |
| endSubdivide(); | |
| if (_subdivides.isNotEmpty) { | |
| throw "Can't enter a phase while in a subdivide"; | |
| } | |
| _phaseTimings[_currentPhase.index].addRuntime( | |
| _phaseStopwatch.elapsedMicroseconds, | |
| ); | |
| _phaseStopwatch.reset(); | |
| _currentPhase = phase; | |
| beginSubdivide(BenchmarkSubdivides.subdividesUnaccountedFor); | |
| } | |
| void stop() { | |
| enterPhase(BenchmarkPhases.end); | |
| _totalStopwatch.stop(); | |
| if (_subdivides.isEmpty) { | |
| throw "System subdivide removed."; | |
| } | |
| endSubdivide(); | |
| if (_subdivides.isNotEmpty) { | |
| throw "Can't stop while in a subdivide"; | |
| } | |
| } | |
| Map<String, Object?> toJson() { | |
| return <String, Object?>{ | |
| "totalTime": _totalStopwatch.elapsedMicroseconds, | |
| "phases": _phaseTimings, | |
| }; | |
| } | |
| } | |
| // Coverage-ignore(suite): Not run. | |
| class PhaseTiming { | |
| final BenchmarkPhases phase; | |
| int _runtime = 0; | |
| final List<SubdivideTiming> subdivides = new List<SubdivideTiming>.generate( | |
| BenchmarkSubdivides.values.length, | |
| (index) { | |
| assert(BenchmarkSubdivides.values[index].index == index); | |
| return new SubdivideTiming(BenchmarkSubdivides.values[index]); | |
| }, | |
| growable: false, | |
| ); | |
| new(this.phase); | |
| void addRuntime(int runtime) { | |
| _runtime += runtime; | |
| } | |
| Map<String, Object?> toJson() { | |
| List<SubdivideTiming> enteredSubdivides = []; | |
| int subdivideRuntime = 0; | |
| for (SubdivideTiming subdivide in subdivides) { | |
| if (subdivide._count > 0) { | |
| enteredSubdivides.add(subdivide); | |
| subdivideRuntime += subdivide._runtime; | |
| } | |
| } | |
| return <String, Object?>{ | |
| "phase": phase.name, | |
| "runtime": _runtime, | |
| "subdivides": enteredSubdivides, | |
| "estimatedSubdividesOverhead": _runtime - subdivideRuntime, | |
| }; | |
| } | |
| } | |
| // Coverage-ignore(suite): Not run. | |
| class SubdivideTiming { | |
| final BenchmarkSubdivides phase; | |
| int _runtime = 0; | |
| int _count = 0; | |
| new(this.phase); | |
| void addRuntime(int runtime, {required bool addAsCount}) { | |
| _runtime += runtime; | |
| if (addAsCount) { | |
| _count++; | |
| } | |
| } | |
| Map<String, Object?> toJson() { | |
| return <String, Object?>{ | |
| "phase": phase.name, | |
| "runtime": _runtime, | |
| "count": _count, | |
| }; | |
| } | |
| } | |
| enum BenchmarkPhases { | |
| implicitInitialization, | |
| loadSDK, | |
| loadAdditionalDillModules, | |
| dill_buildOutlines, | |
| dill_finalizeExports, | |
| outline_kernelBuildOutlines, | |
| outline_resolveParts, | |
| outline_buildNameSpaces, | |
| outline_becomeCoreLibrary, | |
| outline_buildScopes, | |
| outline_computeLibraryScopes, | |
| outline_setupTopAndBottomTypes, | |
| outline_resolveTypes, | |
| outline_computeVariances, | |
| outline_computeDefaultTypes, | |
| outline_checkSemantics, | |
| outline_finishTypeParameters, | |
| outline_createTypeInferenceEngine, | |
| outline_computeSupertypes, | |
| outline_buildComponent, | |
| outline_installDefaultSupertypes, | |
| outline_installSyntheticConstructors, | |
| outline_resolveConstructors, | |
| outline_link, | |
| outline_computeCoreTypes, | |
| outline_buildClassHierarchy, | |
| outline_checkSupertypes, | |
| outline_buildClassHierarchyMembers, | |
| outline_computeHierarchy, | |
| outline_installTypedefTearOffs, | |
| outline_prepareTopLevelInference, | |
| outline_performRedirectingFactoryInference, | |
| outline_computeMemberTypes, | |
| outline_performTopLevelInference, | |
| outline_checkOverrides, | |
| outline_checkAbstractMembers, | |
| outline_computeFieldPromotability, | |
| outline_checkMixins, | |
| outline_buildOutlineExpressions, | |
| outline_checkTypes, | |
| outline_checkRedirectingFactories, | |
| outline_finishSynthesizedParameters, | |
| outline_checkMainMethods, | |
| outline_installAllComponentProblems, | |
| body_buildBodies, | |
| body_checkMixinSuperAccesses, | |
| body_finishSynthesizedParameters, | |
| body_finishDeferredLoadTearoffs, | |
| body_finishNoSuchMethodForwarders, | |
| body_collectSourceClasses, | |
| body_finishNativeMethods, | |
| body_finishAugmentationMethods, | |
| body_finishAllConstructors, | |
| body_validateDynamicModule, | |
| body_runBuildTransformations, | |
| body_verify, | |
| body_installAllComponentProblems, | |
| printComponentText, | |
| omitPlatform, | |
| writeComponent, | |
| benchmarkAstVisit, | |
| incremental_setupPackages, | |
| incremental_ensurePlatform, | |
| incremental_invalidate, | |
| incremental_experimentalInvalidation, | |
| incremental_rewriteEntryPointsIfPart, | |
| incremental_cleanup, | |
| incremental_loadEnsureLoadedComponents, | |
| incremental_setupInLoop, | |
| incremental_precompileMacros, | |
| incremental_experimentalInvalidationPatchUpScopes, | |
| incremental_hierarchy, | |
| incremental_performDillUsageTracking, | |
| incremental_releaseAncillaryResources, | |
| incremental_experimentalCompilationPostCompilePatchup, | |
| incremental_calculateOutputLibrariesAndIssueLibraryProblems, | |
| incremental_convertSourceLibraryBuildersToDill, | |
| incremental_end, | |
| // add more here | |
| // | |
| end, | |
| unknown, | |
| unknownDillTarget, | |
| unknownComputeNeededPrecompilations, | |
| unknownBuildOutlines, | |
| unknownBuildComponent, | |
| unknownGenerateKernelInternal, | |
| } | |
| enum BenchmarkSubdivides { | |
| subdividesUnaccountedFor, | |
| tokenize, | |
| body_buildBody_benchmark_specific_diet_parser, | |
| body_buildBody_benchmark_specific_parser, | |
| diet_listener_buildFields, | |
| diet_listener_buildFunctionBody_parseFunctionBody, | |
| diet_listener_buildPrimaryConstructor, | |
| diet_listener_buildPrimaryConstructorBody, | |
| diet_listener_buildRedirectingFactoryMethod, | |
| resolver_createBodyBuilder, | |
| resolver_buildFunctionBody, | |
| inferImplicitFieldType, | |
| inferFieldInitializer, | |
| inferFunctionBody, | |
| inferInitializers, | |
| inferMetadata, | |
| inferParameterInitializer, | |
| inferRedirectingFactoryTypeArguments, | |
| buildOutlineExpressions, | |
| } |