Skip to content

Commit 85030bd

Browse files
authored
add json serializable benchmark (#3545)
1 parent daf5cbd commit 85030bd

File tree

5 files changed

+310
-7
lines changed

5 files changed

+310
-7
lines changed

working/macros/example/benchmark/simple.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import 'src/checks_extensions.dart' as checks_extensions;
3232
import 'src/data_class.dart' as data_class;
3333
import 'src/functional_widget.dart' as functional_widget;
3434
import 'src/injectable.dart' as injectable;
35+
import 'src/json_serializable.dart' as json_serializable;
3536

3637
final _watch = Stopwatch()..start();
3738
void _log(String message) {
@@ -57,7 +58,8 @@ final argParser = ArgParser()
5758
'ChecksExtensions',
5859
'DataClass',
5960
'Injectable',
60-
'FunctionalWidget'
61+
'FunctionalWidget',
62+
'JsonSerializable',
6163
],
6264
mandatory: true)
6365
..addFlag('help', negatable: false, hide: true);
@@ -107,6 +109,7 @@ Macro: $macro
107109
'DataClass' => File('lib/data_class.dart'),
108110
'Injectable' => File('lib/injectable.dart'),
109111
'FunctionalWidget' => File('lib/functional_widget.dart'),
112+
'JsonSerializable' => File('lib/json_serializable.dart'),
110113
_ => throw UnsupportedError('Unrecognized macro $macro'),
111114
};
112115
if (!macroFile.existsSync()) {
@@ -122,6 +125,8 @@ Macro: $macro
122125
'Injectable' => Uri.parse('package:macro_proposal/injectable.dart'),
123126
'FunctionalWidget' =>
124127
Uri.parse('package:macro_proposal/functional_widget.dart'),
128+
'JsonSerializable' =>
129+
Uri.parse('package:macro_proposal/json_serializable.dart'),
125130
_ => throw UnsupportedError('Unrecognized macro $macro'),
126131
};
127132
var macroConstructors = switch (macro) {
@@ -140,6 +145,9 @@ Macro: $macro
140145
'FunctionalWidget' => {
141146
'FunctionalWidget': [''],
142147
},
148+
'JsonSerializable' => {
149+
'JsonSerializable': [''],
150+
},
143151
_ => throw UnsupportedError('Unrecognized macro $macro'),
144152
};
145153

@@ -183,6 +191,7 @@ Macro: $macro
183191
'DataClass' => data_class.runBenchmarks(executor, macroUri),
184192
'Injectable' => injectable.runBenchmarks(executor, macroUri),
185193
'FunctionalWidget' => functional_widget.runBenchmarks(executor, macroUri),
194+
'JsonSerializable' => json_serializable.runBenchmarks(executor, macroUri),
186195
_ => throw UnsupportedError('Unrecognized macro $macro'),
187196
};
188197
await executor.close();
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
2+
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
3+
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
4+
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
5+
import 'package:benchmark_harness/benchmark_harness.dart';
6+
7+
import 'checks_extensions.dart';
8+
import 'shared.dart';
9+
10+
Future<void> runBenchmarks(MacroExecutor executor, Uri macroUri) async {
11+
final introspector = SimpleDefinitionPhaseIntrospector(declarations: {
12+
myClass.identifier: myClass,
13+
objectClass.identifier: objectClass,
14+
boolClass.identifier: boolClass,
15+
intClass.identifier: intClass,
16+
stringClass.identifier: stringClass,
17+
}, identifiers: {
18+
Uri.parse('dart:core'): {
19+
'bool': boolIdentifier,
20+
'int': intIdentifier,
21+
'dynamic': dynamicIdentifeir,
22+
'String': stringIdentifier,
23+
'Map': mapIdentifier,
24+
'Object': objectIdentifier,
25+
}
26+
}, constructors: {}, enumValues: {}, fields: {
27+
myClass: myClassFields
28+
}, methods: {});
29+
final identifierDeclarations = {
30+
...introspector.declarations,
31+
for (final constructors in introspector.constructors.values)
32+
for (final constructor in constructors)
33+
constructor.identifier: constructor,
34+
for (final methods in introspector.methods.values)
35+
for (final method in methods) method.identifier: method,
36+
for (final fields in introspector.fields.values)
37+
for (final field in fields) field.identifier: field,
38+
};
39+
final instantiateBenchmark =
40+
JsonSerializableInstantiateBenchmark(executor, macroUri);
41+
await instantiateBenchmark.report();
42+
final instanceId = instantiateBenchmark.instanceIdentifier;
43+
final typesBenchmark = JsonSerializableTypesPhaseBenchmark(
44+
executor, macroUri, instanceId, introspector);
45+
await typesBenchmark.report();
46+
BuildAugmentationLibraryBenchmark.reportAndPrint(
47+
executor,
48+
[if (typesBenchmark.result != null) typesBenchmark.result!],
49+
identifierDeclarations);
50+
final declarationsBenchmark = JsonSerializableDeclarationsPhaseBenchmark(
51+
executor, macroUri, instanceId, introspector);
52+
await declarationsBenchmark.report();
53+
BuildAugmentationLibraryBenchmark.reportAndPrint(
54+
executor,
55+
[if (declarationsBenchmark.result != null) declarationsBenchmark.result!],
56+
identifierDeclarations);
57+
introspector.constructors[myClass] = myClassConstructors;
58+
final definitionsBenchmark = JsonSerializableDefinitionPhaseBenchmark(
59+
executor, macroUri, instanceId, introspector);
60+
await definitionsBenchmark.report();
61+
BuildAugmentationLibraryBenchmark.reportAndPrint(
62+
executor,
63+
[if (definitionsBenchmark.result != null) definitionsBenchmark.result!],
64+
identifierDeclarations);
65+
}
66+
67+
class JsonSerializableInstantiateBenchmark extends AsyncBenchmarkBase {
68+
final MacroExecutor executor;
69+
final Uri macroUri;
70+
late MacroInstanceIdentifier instanceIdentifier;
71+
72+
JsonSerializableInstantiateBenchmark(this.executor, this.macroUri)
73+
: super('JsonSerializableInstantiate');
74+
75+
Future<void> run() async {
76+
instanceIdentifier = await executor.instantiateMacro(
77+
macroUri, 'JsonSerializable', '', Arguments([], {}));
78+
}
79+
}
80+
81+
class JsonSerializableTypesPhaseBenchmark extends AsyncBenchmarkBase {
82+
final MacroExecutor executor;
83+
final Uri macroUri;
84+
final MacroInstanceIdentifier instanceIdentifier;
85+
final TypePhaseIntrospector introspector;
86+
MacroExecutionResult? result;
87+
88+
JsonSerializableTypesPhaseBenchmark(
89+
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
90+
: super('JsonSerializableTypesPhase');
91+
92+
Future<void> run() async {
93+
if (instanceIdentifier.shouldExecute(
94+
DeclarationKind.classType, Phase.types)) {
95+
result = await executor.executeTypesPhase(
96+
instanceIdentifier, myClass, introspector);
97+
}
98+
}
99+
}
100+
101+
class JsonSerializableDeclarationsPhaseBenchmark extends AsyncBenchmarkBase {
102+
final MacroExecutor executor;
103+
final Uri macroUri;
104+
final MacroInstanceIdentifier instanceIdentifier;
105+
final DeclarationPhaseIntrospector introspector;
106+
107+
MacroExecutionResult? result;
108+
109+
JsonSerializableDeclarationsPhaseBenchmark(
110+
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
111+
: super('JsonSerializableDeclarationsPhase');
112+
113+
Future<void> run() async {
114+
result = null;
115+
if (instanceIdentifier.shouldExecute(
116+
DeclarationKind.classType, Phase.declarations)) {
117+
result = await executor.executeDeclarationsPhase(
118+
instanceIdentifier, myClass, introspector);
119+
}
120+
}
121+
}
122+
123+
class JsonSerializableDefinitionPhaseBenchmark extends AsyncBenchmarkBase {
124+
final MacroExecutor executor;
125+
final Uri macroUri;
126+
final MacroInstanceIdentifier instanceIdentifier;
127+
final DefinitionPhaseIntrospector introspector;
128+
129+
MacroExecutionResult? result;
130+
131+
JsonSerializableDefinitionPhaseBenchmark(
132+
this.executor, this.macroUri, this.instanceIdentifier, this.introspector)
133+
: super('JsonSerializableDefinitionPhase');
134+
135+
Future<void> run() async {
136+
result = null;
137+
if (instanceIdentifier.shouldExecute(
138+
DeclarationKind.classType, Phase.definitions)) {
139+
result = await executor.executeDefinitionsPhase(
140+
instanceIdentifier, myClass, introspector);
141+
}
142+
}
143+
}
144+
145+
final myClassIdentifier =
146+
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass');
147+
final myClass = ClassDeclarationImpl(
148+
id: RemoteInstance.uniqueId,
149+
identifier: myClassIdentifier,
150+
library: fooLibrary,
151+
metadata: [],
152+
interfaces: [],
153+
hasAbstract: false,
154+
hasBase: false,
155+
hasExternal: false,
156+
hasFinal: false,
157+
hasInterface: false,
158+
hasMixin: false,
159+
hasSealed: false,
160+
mixins: [],
161+
superclass: NamedTypeAnnotationImpl(
162+
id: RemoteInstance.uniqueId,
163+
isNullable: false,
164+
identifier: objectIdentifier,
165+
typeArguments: [],
166+
),
167+
typeParameters: []);
168+
169+
final myClassFields = [
170+
FieldDeclarationImpl(
171+
definingType: myClassIdentifier,
172+
id: RemoteInstance.uniqueId,
173+
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myString'),
174+
library: fooLibrary,
175+
metadata: [],
176+
hasAbstract: false,
177+
hasExternal: false,
178+
hasFinal: true,
179+
hasLate: false,
180+
isStatic: false,
181+
type: stringType),
182+
FieldDeclarationImpl(
183+
definingType: myClassIdentifier,
184+
id: RemoteInstance.uniqueId,
185+
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myBool'),
186+
library: fooLibrary,
187+
metadata: [],
188+
hasAbstract: false,
189+
hasExternal: false,
190+
hasFinal: true,
191+
hasLate: false,
192+
isStatic: false,
193+
type: boolType),
194+
];
195+
196+
final myClassConstructors = [
197+
ConstructorDeclarationImpl(
198+
id: RemoteInstance.uniqueId,
199+
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'fromJson'),
200+
library: fooLibrary,
201+
metadata: [],
202+
hasBody: false,
203+
hasExternal: false,
204+
namedParameters: [],
205+
positionalParameters: [
206+
ParameterDeclarationImpl(
207+
id: RemoteInstance.uniqueId,
208+
identifier:
209+
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'json'),
210+
library: fooLibrary,
211+
metadata: [],
212+
isNamed: false,
213+
isRequired: true,
214+
type: NamedTypeAnnotationImpl(
215+
id: RemoteInstance.uniqueId,
216+
isNullable: false,
217+
identifier: mapIdentifier,
218+
typeArguments: [stringType, dynamicType]))
219+
],
220+
returnType: myClassType,
221+
typeParameters: [],
222+
definingType: myClass.identifier,
223+
isFactory: true),
224+
];

working/macros/example/benchmark/src/shared.dart

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
2323
List<MacroExecutionResult> results,
2424
Map<Identifier, Declaration> identifierDeclarations,
2525
) {
26+
for (var result in results) {
27+
for (var diagnostic in result.diagnostics) {
28+
print(diagnostic.message.message);
29+
}
30+
}
2631
final benchmark = BuildAugmentationLibraryBenchmark(
2732
executor, results, identifierDeclarations);
2833
benchmark.report();
@@ -198,8 +203,8 @@ class SimpleDefinitionPhaseIntrospector
198203
required super.methods});
199204

200205
@override
201-
Future<Declaration> declarationOf(Identifier identifier) =>
202-
throw UnimplementedError();
206+
Future<Declaration> declarationOf(Identifier identifier) async =>
207+
declarations[identifier]!;
203208

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

246251
final boolIdentifier =
247252
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bool');
253+
final dynamicIdentifeir =
254+
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'dynamic');
248255
final intIdentifier = IdentifierImpl(id: RemoteInstance.uniqueId, name: 'int');
256+
final mapIdentifier = IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Map');
249257
final objectIdentifier =
250258
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object');
251259
final stringIdentifier =
@@ -256,6 +264,11 @@ final boolType = NamedTypeAnnotationImpl(
256264
identifier: boolIdentifier,
257265
isNullable: false,
258266
typeArguments: const []);
267+
final dynamicType = NamedTypeAnnotationImpl(
268+
id: RemoteInstance.uniqueId,
269+
identifier: dynamicIdentifeir,
270+
isNullable: false,
271+
typeArguments: const []);
259272
final intType = NamedTypeAnnotationImpl(
260273
id: RemoteInstance.uniqueId,
261274
identifier: intIdentifier,
@@ -266,16 +279,70 @@ final stringType = NamedTypeAnnotationImpl(
266279
identifier: stringIdentifier,
267280
isNullable: false,
268281
typeArguments: const []);
282+
283+
final dartCoreLibrary = LibraryImpl(
284+
id: RemoteInstance.uniqueId,
285+
languageVersion: LanguageVersionImpl(3, 0),
286+
metadata: [],
287+
uri: Uri.parse('dart:core'));
269288
final fooLibrary = LibraryImpl(
270289
id: RemoteInstance.uniqueId,
271290
languageVersion: LanguageVersionImpl(3, 0),
272291
metadata: [],
273292
uri: Uri.parse('package:foo/foo.dart'));
274293

294+
final boolClass = ClassDeclarationImpl(
295+
id: RemoteInstance.uniqueId,
296+
identifier: boolIdentifier,
297+
library: dartCoreLibrary,
298+
metadata: [],
299+
interfaces: [],
300+
hasAbstract: false,
301+
hasBase: false,
302+
hasExternal: false,
303+
hasFinal: false,
304+
hasInterface: false,
305+
hasMixin: false,
306+
hasSealed: false,
307+
mixins: [],
308+
superclass: null,
309+
typeParameters: []);
310+
final intClass = ClassDeclarationImpl(
311+
id: RemoteInstance.uniqueId,
312+
identifier: intIdentifier,
313+
library: dartCoreLibrary,
314+
metadata: [],
315+
interfaces: [],
316+
hasAbstract: false,
317+
hasBase: false,
318+
hasExternal: false,
319+
hasFinal: false,
320+
hasInterface: false,
321+
hasMixin: false,
322+
hasSealed: false,
323+
mixins: [],
324+
superclass: null,
325+
typeParameters: []);
275326
final objectClass = ClassDeclarationImpl(
276327
id: RemoteInstance.uniqueId,
277328
identifier: objectIdentifier,
278-
library: fooLibrary,
329+
library: dartCoreLibrary,
330+
metadata: [],
331+
interfaces: [],
332+
hasAbstract: false,
333+
hasBase: false,
334+
hasExternal: false,
335+
hasFinal: false,
336+
hasInterface: false,
337+
hasMixin: false,
338+
hasSealed: false,
339+
mixins: [],
340+
superclass: null,
341+
typeParameters: []);
342+
final stringClass = ClassDeclarationImpl(
343+
id: RemoteInstance.uniqueId,
344+
identifier: stringIdentifier,
345+
library: dartCoreLibrary,
279346
metadata: [],
280347
interfaces: [],
281348
hasAbstract: false,

0 commit comments

Comments
 (0)