Skip to content

Commit

Permalink
add json serializable benchmark (#3545)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakemac53 authored Jan 9, 2024
1 parent daf5cbd commit 85030bd
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 7 deletions.
11 changes: 10 additions & 1 deletion working/macros/example/benchmark/simple.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import 'src/checks_extensions.dart' as checks_extensions;
import 'src/data_class.dart' as data_class;
import 'src/functional_widget.dart' as functional_widget;
import 'src/injectable.dart' as injectable;
import 'src/json_serializable.dart' as json_serializable;

final _watch = Stopwatch()..start();
void _log(String message) {
Expand All @@ -57,7 +58,8 @@ final argParser = ArgParser()
'ChecksExtensions',
'DataClass',
'Injectable',
'FunctionalWidget'
'FunctionalWidget',
'JsonSerializable',
],
mandatory: true)
..addFlag('help', negatable: false, hide: true);
Expand Down Expand Up @@ -107,6 +109,7 @@ Macro: $macro
'DataClass' => File('lib/data_class.dart'),
'Injectable' => File('lib/injectable.dart'),
'FunctionalWidget' => File('lib/functional_widget.dart'),
'JsonSerializable' => File('lib/json_serializable.dart'),
_ => throw UnsupportedError('Unrecognized macro $macro'),
};
if (!macroFile.existsSync()) {
Expand All @@ -122,6 +125,8 @@ Macro: $macro
'Injectable' => Uri.parse('package:macro_proposal/injectable.dart'),
'FunctionalWidget' =>
Uri.parse('package:macro_proposal/functional_widget.dart'),
'JsonSerializable' =>
Uri.parse('package:macro_proposal/json_serializable.dart'),
_ => throw UnsupportedError('Unrecognized macro $macro'),
};
var macroConstructors = switch (macro) {
Expand All @@ -140,6 +145,9 @@ Macro: $macro
'FunctionalWidget' => {
'FunctionalWidget': [''],
},
'JsonSerializable' => {
'JsonSerializable': [''],
},
_ => throw UnsupportedError('Unrecognized macro $macro'),
};

Expand Down Expand Up @@ -183,6 +191,7 @@ Macro: $macro
'DataClass' => data_class.runBenchmarks(executor, macroUri),
'Injectable' => injectable.runBenchmarks(executor, macroUri),
'FunctionalWidget' => functional_widget.runBenchmarks(executor, macroUri),
'JsonSerializable' => json_serializable.runBenchmarks(executor, macroUri),
_ => throw UnsupportedError('Unrecognized macro $macro'),
};
await executor.close();
Expand Down
224 changes: 224 additions & 0 deletions working/macros/example/benchmark/src/json_serializable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
import 'package:benchmark_harness/benchmark_harness.dart';

import 'checks_extensions.dart';
import 'shared.dart';

Future<void> runBenchmarks(MacroExecutor executor, Uri macroUri) async {
final introspector = SimpleDefinitionPhaseIntrospector(declarations: {
myClass.identifier: myClass,
objectClass.identifier: objectClass,
boolClass.identifier: boolClass,
intClass.identifier: intClass,
stringClass.identifier: stringClass,
}, identifiers: {
Uri.parse('dart:core'): {
'bool': boolIdentifier,
'int': intIdentifier,
'dynamic': dynamicIdentifeir,
'String': stringIdentifier,
'Map': mapIdentifier,
'Object': objectIdentifier,
}
}, constructors: {}, enumValues: {}, fields: {
myClass: myClassFields
}, methods: {});
final identifierDeclarations = {
...introspector.declarations,
for (final constructors in introspector.constructors.values)
for (final constructor in constructors)
constructor.identifier: constructor,
for (final methods in introspector.methods.values)
for (final method in methods) method.identifier: method,
for (final fields in introspector.fields.values)
for (final field in fields) field.identifier: field,
};
final instantiateBenchmark =
JsonSerializableInstantiateBenchmark(executor, macroUri);
await instantiateBenchmark.report();
final instanceId = instantiateBenchmark.instanceIdentifier;
final typesBenchmark = JsonSerializableTypesPhaseBenchmark(
executor, macroUri, instanceId, introspector);
await typesBenchmark.report();
BuildAugmentationLibraryBenchmark.reportAndPrint(
executor,
[if (typesBenchmark.result != null) typesBenchmark.result!],
identifierDeclarations);
final declarationsBenchmark = JsonSerializableDeclarationsPhaseBenchmark(
executor, macroUri, instanceId, introspector);
await declarationsBenchmark.report();
BuildAugmentationLibraryBenchmark.reportAndPrint(
executor,
[if (declarationsBenchmark.result != null) declarationsBenchmark.result!],
identifierDeclarations);
introspector.constructors[myClass] = myClassConstructors;
final definitionsBenchmark = JsonSerializableDefinitionPhaseBenchmark(
executor, macroUri, instanceId, introspector);
await definitionsBenchmark.report();
BuildAugmentationLibraryBenchmark.reportAndPrint(
executor,
[if (definitionsBenchmark.result != null) definitionsBenchmark.result!],
identifierDeclarations);
}

class JsonSerializableInstantiateBenchmark extends AsyncBenchmarkBase {
final MacroExecutor executor;
final Uri macroUri;
late MacroInstanceIdentifier instanceIdentifier;

JsonSerializableInstantiateBenchmark(this.executor, this.macroUri)
: super('JsonSerializableInstantiate');

Future<void> run() async {
instanceIdentifier = await executor.instantiateMacro(
macroUri, 'JsonSerializable', '', Arguments([], {}));
}
}

class JsonSerializableTypesPhaseBenchmark extends AsyncBenchmarkBase {
final MacroExecutor executor;
final Uri macroUri;
final MacroInstanceIdentifier instanceIdentifier;
final TypePhaseIntrospector introspector;
MacroExecutionResult? result;

JsonSerializableTypesPhaseBenchmark(
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
: super('JsonSerializableTypesPhase');

Future<void> run() async {
if (instanceIdentifier.shouldExecute(
DeclarationKind.classType, Phase.types)) {
result = await executor.executeTypesPhase(
instanceIdentifier, myClass, introspector);
}
}
}

class JsonSerializableDeclarationsPhaseBenchmark extends AsyncBenchmarkBase {
final MacroExecutor executor;
final Uri macroUri;
final MacroInstanceIdentifier instanceIdentifier;
final DeclarationPhaseIntrospector introspector;

MacroExecutionResult? result;

JsonSerializableDeclarationsPhaseBenchmark(
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
: super('JsonSerializableDeclarationsPhase');

Future<void> run() async {
result = null;
if (instanceIdentifier.shouldExecute(
DeclarationKind.classType, Phase.declarations)) {
result = await executor.executeDeclarationsPhase(
instanceIdentifier, myClass, introspector);
}
}
}

class JsonSerializableDefinitionPhaseBenchmark extends AsyncBenchmarkBase {
final MacroExecutor executor;
final Uri macroUri;
final MacroInstanceIdentifier instanceIdentifier;
final DefinitionPhaseIntrospector introspector;

MacroExecutionResult? result;

JsonSerializableDefinitionPhaseBenchmark(
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
: super('JsonSerializableDefinitionPhase');

Future<void> run() async {
result = null;
if (instanceIdentifier.shouldExecute(
DeclarationKind.classType, Phase.definitions)) {
result = await executor.executeDefinitionsPhase(
instanceIdentifier, myClass, introspector);
}
}
}

final myClassIdentifier =
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass');
final myClass = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: myClassIdentifier,
library: fooLibrary,
metadata: [],
interfaces: [],
hasAbstract: false,
hasBase: false,
hasExternal: false,
hasFinal: false,
hasInterface: false,
hasMixin: false,
hasSealed: false,
mixins: [],
superclass: NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
isNullable: false,
identifier: objectIdentifier,
typeArguments: [],
),
typeParameters: []);

final myClassFields = [
FieldDeclarationImpl(
definingType: myClassIdentifier,
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myString'),
library: fooLibrary,
metadata: [],
hasAbstract: false,
hasExternal: false,
hasFinal: true,
hasLate: false,
isStatic: false,
type: stringType),
FieldDeclarationImpl(
definingType: myClassIdentifier,
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myBool'),
library: fooLibrary,
metadata: [],
hasAbstract: false,
hasExternal: false,
hasFinal: true,
hasLate: false,
isStatic: false,
type: boolType),
];

final myClassConstructors = [
ConstructorDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'fromJson'),
library: fooLibrary,
metadata: [],
hasBody: false,
hasExternal: false,
namedParameters: [],
positionalParameters: [
ParameterDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier:
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'json'),
library: fooLibrary,
metadata: [],
isNamed: false,
isRequired: true,
type: NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
isNullable: false,
identifier: mapIdentifier,
typeArguments: [stringType, dynamicType]))
],
returnType: myClassType,
typeParameters: [],
definingType: myClass.identifier,
isFactory: true),
];
73 changes: 70 additions & 3 deletions working/macros/example/benchmark/src/shared.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
List<MacroExecutionResult> results,
Map<Identifier, Declaration> identifierDeclarations,
) {
for (var result in results) {
for (var diagnostic in result.diagnostics) {
print(diagnostic.message.message);
}
}
final benchmark = BuildAugmentationLibraryBenchmark(
executor, results, identifierDeclarations);
benchmark.report();
Expand Down Expand Up @@ -198,8 +203,8 @@ class SimpleDefinitionPhaseIntrospector
required super.methods});

@override
Future<Declaration> declarationOf(Identifier identifier) =>
throw UnimplementedError();
Future<Declaration> declarationOf(Identifier identifier) async =>
declarations[identifier]!;

@override
Future<TypeAnnotation> inferType(OmittedTypeAnnotation omittedType) =>
Expand Down Expand Up @@ -245,7 +250,10 @@ class SimpleNamedStaticType implements NamedStaticType {

final boolIdentifier =
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bool');
final dynamicIdentifeir =
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'dynamic');
final intIdentifier = IdentifierImpl(id: RemoteInstance.uniqueId, name: 'int');
final mapIdentifier = IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Map');
final objectIdentifier =
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object');
final stringIdentifier =
Expand All @@ -256,6 +264,11 @@ final boolType = NamedTypeAnnotationImpl(
identifier: boolIdentifier,
isNullable: false,
typeArguments: const []);
final dynamicType = NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
identifier: dynamicIdentifeir,
isNullable: false,
typeArguments: const []);
final intType = NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
identifier: intIdentifier,
Expand All @@ -266,16 +279,70 @@ final stringType = NamedTypeAnnotationImpl(
identifier: stringIdentifier,
isNullable: false,
typeArguments: const []);

final dartCoreLibrary = LibraryImpl(
id: RemoteInstance.uniqueId,
languageVersion: LanguageVersionImpl(3, 0),
metadata: [],
uri: Uri.parse('dart:core'));
final fooLibrary = LibraryImpl(
id: RemoteInstance.uniqueId,
languageVersion: LanguageVersionImpl(3, 0),
metadata: [],
uri: Uri.parse('package:foo/foo.dart'));

final boolClass = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: boolIdentifier,
library: dartCoreLibrary,
metadata: [],
interfaces: [],
hasAbstract: false,
hasBase: false,
hasExternal: false,
hasFinal: false,
hasInterface: false,
hasMixin: false,
hasSealed: false,
mixins: [],
superclass: null,
typeParameters: []);
final intClass = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: intIdentifier,
library: dartCoreLibrary,
metadata: [],
interfaces: [],
hasAbstract: false,
hasBase: false,
hasExternal: false,
hasFinal: false,
hasInterface: false,
hasMixin: false,
hasSealed: false,
mixins: [],
superclass: null,
typeParameters: []);
final objectClass = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: objectIdentifier,
library: fooLibrary,
library: dartCoreLibrary,
metadata: [],
interfaces: [],
hasAbstract: false,
hasBase: false,
hasExternal: false,
hasFinal: false,
hasInterface: false,
hasMixin: false,
hasSealed: false,
mixins: [],
superclass: null,
typeParameters: []);
final stringClass = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: stringIdentifier,
library: dartCoreLibrary,
metadata: [],
interfaces: [],
hasAbstract: false,
Expand Down
Loading

0 comments on commit 85030bd

Please sign in to comment.