Skip to content

Commit 1af8233

Browse files
authored
Updates to data class macro benchmarks, add code optimizer benchmark (#3621)
- When benching augmentation library creation, include results from earlier stages - Only do formatting at the very end - Add code optimization at the very end - Make comparisons fair, only call `run` once inside the synchronous benchmarks. Results for code optimization look fairly reasonable, ~25μs (total macro execution takes around 2ms prior to that, ignoring formatting). Formatting is slower but maybe reasonable, around 450 μs. Example run here https://gist.github.com/jakemac53/096b8380db41aa2eda46ae189a510c29. cc @jacob314
1 parent cd5d630 commit 1af8233

File tree

2 files changed

+93
-19
lines changed

2 files changed

+93
-19
lines changed

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

+28-12
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@ import 'package:benchmark_harness/benchmark_harness.dart';
77
import 'shared.dart';
88

99
Future<void> runBenchmarks(MacroExecutor executor, Uri macroUri) async {
10-
final introspector = SimpleDefinitionPhaseIntrospector(declarations: {
11-
myClass.identifier: myClass,
12-
objectClass.identifier: objectClass
13-
}, identifiers: {
10+
final libraryIdentifiers = {
1411
Uri.parse('dart:core'): {
1512
'bool': boolIdentifier,
1613
'int': intIdentifier,
1714
'Object': objectIdentifier,
1815
'String': stringIdentifier,
1916
}
20-
}, constructors: {}, enumValues: {}, fields: {
21-
myClass: myClassFields
22-
}, methods: {
23-
myClass: myClassMethods
24-
});
17+
};
18+
final introspector = SimpleDefinitionPhaseIntrospector(
19+
declarations: {
20+
myClass.identifier: myClass,
21+
objectClass.identifier: objectClass
22+
},
23+
identifiers: libraryIdentifiers,
24+
constructors: {},
25+
enumValues: {},
26+
fields: {myClass: myClassFields},
27+
methods: {myClass: myClassMethods});
2528
final identifierDeclarations = {
2629
...introspector.declarations,
2730
for (final constructors in introspector.constructors.values)
@@ -48,15 +51,28 @@ Future<void> runBenchmarks(MacroExecutor executor, Uri macroUri) async {
4851
await declarationsBenchmark.report();
4952
BuildAugmentationLibraryBenchmark.reportAndPrint(
5053
executor,
51-
[if (declarationsBenchmark.result != null) declarationsBenchmark.result!],
54+
[
55+
if (typesBenchmark.result != null) typesBenchmark.result!,
56+
if (declarationsBenchmark.result != null) declarationsBenchmark.result!,
57+
],
5258
identifierDeclarations);
5359
final definitionsBenchmark = DataClassDefinitionPhaseBenchmark(
5460
executor, macroUri, instanceId, introspector);
5561
await definitionsBenchmark.report();
56-
BuildAugmentationLibraryBenchmark.reportAndPrint(
62+
final rawLibrary = BuildAugmentationLibraryBenchmark.reportAndPrint(
5763
executor,
58-
[if (definitionsBenchmark.result != null) definitionsBenchmark.result!],
64+
[
65+
if (typesBenchmark.result != null) typesBenchmark.result!,
66+
if (declarationsBenchmark.result != null) declarationsBenchmark.result!,
67+
if (definitionsBenchmark.result != null) definitionsBenchmark.result!,
68+
],
5969
identifierDeclarations);
70+
71+
final formattedLibrary = FormatLibraryBenchmark.reportAndPrint(rawLibrary);
72+
73+
CodeOptimizerBenchmark(formattedLibrary, {'MyClass'},
74+
BenchmarkCodeOptimizer(identifiers: libraryIdentifiers))
75+
.reportAndPrint();
6076
}
6177

6278
class DataClassInstantiateBenchmark extends AsyncBenchmarkBase {

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

+65-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
// There is no public API exposed yet, the in progress API lives here.
22
import 'package:_fe_analyzer_shared/src/macros/api.dart';
3+
import 'package:_fe_analyzer_shared/src/macros/code_optimizer.dart';
34
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
45
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
56
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
7+
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
68
import 'package:benchmark_harness/benchmark_harness.dart';
79
import 'package:dart_style/dart_style.dart';
810

9-
class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
11+
/// A benchmark which only calls `run` once inside `excersize`.
12+
class RunOnceBenchmarkBase extends BenchmarkBase {
13+
RunOnceBenchmarkBase(super.name);
14+
15+
@override
16+
void exercise() {
17+
run();
18+
}
19+
}
20+
21+
class BuildAugmentationLibraryBenchmark extends RunOnceBenchmarkBase {
1022
final MacroExecutor executor;
1123
final List<MacroExecutionResult> results;
1224

@@ -18,7 +30,7 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
1830
this.executor, this.results, this.identifierDeclarations)
1931
: super('AugmentationLibrary');
2032

21-
static void reportAndPrint(
33+
static String reportAndPrint(
2234
MacroExecutor executor,
2335
List<MacroExecutionResult> results,
2436
Map<Identifier, Declaration> identifierDeclarations,
@@ -31,8 +43,7 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
3143
final benchmark = BuildAugmentationLibraryBenchmark(
3244
executor, results, identifierDeclarations);
3345
benchmark.report();
34-
final formatBenchmark = FormatLibraryBenchmark(benchmark.library)..report();
35-
print('${formatBenchmark.formattedResult}');
46+
return benchmark.library;
3647
}
3748

3849
void run() {
@@ -48,7 +59,7 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
4859
kind: IdentifierKind.topLevelMember,
4960
name: identifier.name,
5061
staticScope: null,
51-
uri: null);
62+
uri: dartCore);
5263
} else {
5364
final declaration = identifierDeclarations[identifier];
5465
String? staticScope;
@@ -79,9 +90,11 @@ class BuildAugmentationLibraryBenchmark extends BenchmarkBase {
7990
(annotation) =>
8091
throw UnsupportedError('Omitted types are not supported!'));
8192
}
93+
94+
static final dartCore = Uri.parse('dart:core');
8295
}
8396

84-
class FormatLibraryBenchmark extends BenchmarkBase {
97+
class FormatLibraryBenchmark extends RunOnceBenchmarkBase {
8598
final formatter = DartFormatter();
8699
final String library;
87100
late String _formattedResult;
@@ -90,7 +103,7 @@ class FormatLibraryBenchmark extends BenchmarkBase {
90103
.replaceAll('/*augment*/', 'augment')
91104
.replaceAll('on FakeTypeForFormatting {', '{');
92105

93-
FormatLibraryBenchmark(String library)
106+
FormatLibraryBenchmark._(String library)
94107
: library = _prepareLibrary(library),
95108
super('FormatLibrary');
96109

@@ -118,6 +131,51 @@ class FormatLibraryBenchmark extends BenchmarkBase {
118131
void run() {
119132
_formattedResult = formatter.format(library);
120133
}
134+
135+
static String reportAndPrint(String library) {
136+
final formatBenchmark = FormatLibraryBenchmark._(library)..report();
137+
print('${formatBenchmark.formattedResult}');
138+
return formatBenchmark.formattedResult;
139+
}
140+
}
141+
142+
class CodeOptimizerBenchmark extends RunOnceBenchmarkBase {
143+
final String library;
144+
final Set<String> libraryDeclarationNames;
145+
final BenchmarkCodeOptimizer optimizer;
146+
late String optimizedLibrary;
147+
148+
CodeOptimizerBenchmark(
149+
this.library, this.libraryDeclarationNames, this.optimizer)
150+
: super('CodeOptimizer');
151+
152+
void run() {
153+
optimizedLibrary = Edit.applyList(
154+
optimizer.optimize(library,
155+
libraryDeclarationNames: libraryDeclarationNames,
156+
scannerConfiguration: ScannerConfiguration(
157+
enableExtensionMethods: true,
158+
enableNonNullable: true,
159+
enableTripleShift: true,
160+
forAugmentationLibrary: true)),
161+
library);
162+
}
163+
164+
void reportAndPrint() {
165+
report();
166+
print(optimizedLibrary);
167+
}
168+
}
169+
170+
class BenchmarkCodeOptimizer extends CodeOptimizer {
171+
final Map<Uri, Map<String, Identifier>> identifiers;
172+
173+
BenchmarkCodeOptimizer({required this.identifiers});
174+
175+
@override
176+
Set<String> getImportedNames(String uriStr) {
177+
return (identifiers[Uri.parse(uriStr)] ?? {}).keys.toSet();
178+
}
121179
}
122180

123181
abstract mixin class Fake {

0 commit comments

Comments
 (0)