Skip to content

Commit 6273587

Browse files
jensjohaCommit Queue
authored andcommitted
[analyzer] Add benchmark for many 'prefer_single_quotes' violations
For the select all one I get 50: 0.310976 seconds 100: 1.054733 seconds 200: 5.535353 seconds 400: 36.099675 seconds 800: 247.919461 seconds Disabling that (so I can go higher) for the "Subsequent action call 1" (simulating moving the cursor down a line in the IDE in the file) I get 100: 0.047451 seconds 200: 0.079821 seconds 400: 0.160073 seconds 800: 0.451288 seconds 1600: 1.311321 seconds 3200: 5.549266 seconds 6400: 32.955526 seconds Note that for all of this it's just a single file with <size> lines looking like ``` "num": "num", ``` so even though 6400 is a "large number" it's not entirely unrealistic. Change-Id: I5c2a51822c0748b4a71d98cef9caeb3e30aec5bc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425503 Commit-Queue: Jens Johansen <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 4405a5c commit 6273587

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed

pkg/analysis_server/tool/benchmark_tools/lsp_messages.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@ class LspMessages {
4242
};
4343
}
4444

45+
static Map<String, dynamic> codeActionRange(
46+
int id,
47+
Uri uri, {
48+
required int lineFrom,
49+
required int characterFrom,
50+
required int lineTo,
51+
required int characterTo,
52+
}) {
53+
return {
54+
'jsonrpc': '2.0',
55+
'id': id,
56+
'method': 'textDocument/codeAction',
57+
'params': {
58+
'textDocument': {'uri': '$uri'},
59+
'range': {
60+
'start': {'line': lineFrom, 'character': characterFrom},
61+
'end': {'line': lineTo, 'character': characterTo},
62+
},
63+
'context': {'diagnostics': [], 'triggerKind': 2},
64+
},
65+
'clientRequestTime': DateTime.now().millisecondsSinceEpoch,
66+
};
67+
}
68+
4569
static Map<String, dynamic> completion(
4670
Uri uri,
4771
int id, {
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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+
7+
import '../language_server_benchmark.dart';
8+
import '../lsp_messages.dart';
9+
import '../run_utils.dart';
10+
11+
/// Create a single file with a variable amount of double-quotes in it that will
12+
/// violate the prefer_single_quites lint. Pretend to be a user in an IDE moving
13+
/// the cursor a bit and then selecting everything.
14+
Future<void> main(List<String> args) async {
15+
await runHelper(
16+
args,
17+
LspManyPreferSingleQuotesViolationsBenchmark.new,
18+
createData,
19+
// Currently going higher is very slow.
20+
// For the select-all one I get:
21+
// * 50: 0.310976 seconds
22+
// * 100: 1.054733 seconds
23+
// * 200: 5.535353 seconds
24+
// * 400: 36.099675 seconds
25+
// * 800: 247.919461 seconds
26+
sizeOptions: [25, 50, 100, 200],
27+
extraIterations: (_) => [null],
28+
runAsLsp: true,
29+
);
30+
}
31+
32+
RunDetails createData(
33+
Uri packageDirUri,
34+
Uri outerDirForAdditionalData,
35+
int size,
36+
dynamic unused,
37+
List<String> args, {
38+
// unused
39+
required dynamic extraInformation,
40+
}) {
41+
Uri libDirUri = packageDirUri.resolve('lib/');
42+
Directory.fromUri(libDirUri).createSync();
43+
44+
// Write analysis_options.
45+
File.fromUri(
46+
packageDirUri.resolve('analysis_options.yaml'),
47+
).writeAsStringSync('''
48+
linter:
49+
rules:
50+
- prefer_single_quotes
51+
''');
52+
53+
var mainFileUri = libDirUri.resolve('main.dart');
54+
var mainFileContent = StringBuffer();
55+
mainFileContent.writeln('Map<String, String> foo = {');
56+
for (int i = 0; i < size; i++) {
57+
mainFileContent.writeln('"$i": "$i",');
58+
}
59+
mainFileContent.writeln('};');
60+
var mainFileContentString = mainFileContent.toString();
61+
File.fromUri(mainFileUri).writeAsStringSync(mainFileContentString);
62+
63+
return RunDetails(
64+
mainFile: FileContentPair(mainFileUri, mainFileContentString),
65+
);
66+
}
67+
68+
class FileContentPair {
69+
final Uri uri;
70+
final String content;
71+
72+
FileContentPair(this.uri, this.content);
73+
}
74+
75+
class LspManyPreferSingleQuotesViolationsBenchmark
76+
extends DartLanguageServerBenchmark {
77+
@override
78+
final Uri rootUri;
79+
@override
80+
final Uri cacheFolder;
81+
82+
final RunDetails runDetails;
83+
84+
LspManyPreferSingleQuotesViolationsBenchmark(
85+
super.args,
86+
this.rootUri,
87+
this.cacheFolder,
88+
this.runDetails,
89+
) : super(useLspProtocol: true);
90+
91+
@override
92+
LaunchFrom get launchFrom => LaunchFrom.Dart;
93+
94+
@override
95+
Future<void> afterInitialization() async {
96+
int lines = runDetails.mainFile.content.split('\n').length;
97+
await send(
98+
LspMessages.open(runDetails.mainFile.uri, 1, runDetails.mainFile.content),
99+
);
100+
101+
// Send 'textDocument/codeAction'...
102+
var codeActionStopwatch = Stopwatch()..start();
103+
await (await send(
104+
LspMessages.codeAction(
105+
largestIdSeen + 1,
106+
runDetails.mainFile.uri,
107+
// Basically on the quote in `: "1"`
108+
line: 1,
109+
character: 7,
110+
),
111+
))!.completer.future;
112+
codeActionStopwatch.stop();
113+
durationInfo.add(
114+
DurationInfo('First code action call', codeActionStopwatch.elapsed),
115+
);
116+
117+
for (int i = 1; i <= 2; i++) {
118+
var codeActionStopwatch = Stopwatch()..start();
119+
await (await send(
120+
LspMessages.codeAction(
121+
largestIdSeen + 1,
122+
runDetails.mainFile.uri,
123+
// Basically on the quote in `: "2"` (etc)
124+
line: 1 + i,
125+
character: 7,
126+
),
127+
))!.completer.future;
128+
codeActionStopwatch.stop();
129+
durationInfo.add(
130+
DurationInfo('Subsequent action call $i', codeActionStopwatch.elapsed),
131+
);
132+
}
133+
134+
{
135+
var codeActionStopwatch = Stopwatch()..start();
136+
// The user seelects all (or, at lest a big chunk) and the IDE
137+
// sends a code action request for the selected range.
138+
await (await send(
139+
LspMessages.codeActionRange(
140+
largestIdSeen + 1,
141+
runDetails.mainFile.uri,
142+
lineFrom: 0,
143+
characterFrom: 0,
144+
lineTo: lines - 1,
145+
characterTo: 0,
146+
),
147+
))!.completer.future;
148+
codeActionStopwatch.stop();
149+
durationInfo.add(
150+
DurationInfo(
151+
'Select all code action call',
152+
codeActionStopwatch.elapsed,
153+
),
154+
);
155+
}
156+
}
157+
}
158+
159+
class RunDetails {
160+
final FileContentPair mainFile;
161+
162+
RunDetails({required this.mainFile});
163+
}

0 commit comments

Comments
 (0)