Skip to content

Commit b380c03

Browse files
jensjohaCommit Queue
authored andcommitted
[parser] Add first iteration of a parser benchmark
Modelled after the scanner_benchmark. In jit mode it's currently at around 14 tokens/ms for pkg/front_end/lib/src/type_inference/inference_visitor.dart and 20 tokens/ms for pkg/analyzer/lib/src/dart/ast/ast.dart. In aot mode it's currently at around 18 tokens/ms for pkg/front_end/lib/src/type_inference/inference_visitor.dart and 25 tokens/ms for pkg/analyzer/lib/src/dart/ast/ast.dart. Change-Id: Ib080b68b99ddbddc16321237afb0d0d83fccdd11 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/439720 Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Jens Johansen <[email protected]>
1 parent b8cfc77 commit b380c03

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
import 'dart:typed_data';
7+
8+
import 'package:_fe_analyzer_shared/src/messages/codes.dart';
9+
import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart';
10+
import 'package:_fe_analyzer_shared/src/parser/listener.dart';
11+
import 'package:_fe_analyzer_shared/src/parser/parser_impl.dart';
12+
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
13+
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
14+
15+
void main(List<String> args) {
16+
if (args.length != 1) {
17+
throw "Expected 1 argument: <dart file>.";
18+
}
19+
File f = new File(args.single);
20+
if (!f.existsSync()) {
21+
throw "File $f doesn't exist.";
22+
}
23+
Uint8List contentBytes = f.readAsBytesSync();
24+
ScannerResult scanResult = scan(
25+
contentBytes,
26+
configuration: new ScannerConfiguration(enableTripleShift: true),
27+
includeComments: true,
28+
);
29+
30+
const int iterations = 1000;
31+
32+
int countTokens = 0;
33+
{
34+
Token t = scanResult.tokens;
35+
while (!t.isEof) {
36+
countTokens++;
37+
t = t.next!;
38+
}
39+
}
40+
41+
// TODO: Should we make 1000 copies of the tokens?
42+
// Or maybe scan 1000 times?
43+
/*
44+
List<Token> tokenStarts = [];
45+
tokenStarts.add(scanResult.tokens);
46+
while (tokenStarts.length < iterations) {
47+
tokenStarts.add(
48+
scan(
49+
contentBytes,
50+
configuration: new ScannerConfiguration(enableTripleShift: true),
51+
includeComments: true,
52+
).tokens,
53+
);
54+
}
55+
*/
56+
57+
Listener listener = new NullListener();
58+
if (f.path == "42") {
59+
// Let's not let it optimize too many things away or do weird optimizations
60+
// that it can't do in practise.
61+
listener = new FooListener(f.uri);
62+
}
63+
64+
int numErrors = 0;
65+
Stopwatch stopwatch = new Stopwatch()..start();
66+
int lengthProcessed = countTokens;
67+
68+
for (int i = 0; i < iterations; i++) {
69+
Parser parser = new Parser(listener, allowPatterns: true);
70+
Token after = parser.parseUnit(scanResult.tokens);
71+
if (!after.isEof) {
72+
throw "parsed returned before eof?!?";
73+
}
74+
if (listener is NullListener && listener.hasErrors) {
75+
numErrors++;
76+
}
77+
}
78+
79+
stopwatch.stop();
80+
print(
81+
"Parsed $lengthProcessed tokens $iterations times "
82+
"in ${stopwatch.elapsed}",
83+
);
84+
print("Found errors $numErrors times");
85+
double lengthPerMicrosecond =
86+
(lengthProcessed * iterations) / stopwatch.elapsedMicroseconds;
87+
print("That's $lengthPerMicrosecond tokens per microsecond");
88+
print("");
89+
}
90+
91+
class FooListener extends StackListener {
92+
List<Message> problems = [];
93+
94+
@override
95+
final Uri uri;
96+
97+
FooListener(this.uri);
98+
99+
@override
100+
void addProblem(
101+
Message message,
102+
int charOffset,
103+
int length, {
104+
bool wasHandled = false,
105+
List<LocatedMessage>? context,
106+
}) {
107+
if (charOffset == 42) {
108+
throw "$message $charOffset $length $wasHandled $context";
109+
}
110+
problems.add(message);
111+
}
112+
113+
@override
114+
Never internalProblem(Message message, int charOffset, Uri uri) {
115+
throw UnimplementedError();
116+
}
117+
118+
@override
119+
bool get isDartLibrary => false;
120+
}

0 commit comments

Comments
 (0)