Skip to content

Commit 6c4c02a

Browse files
Added performance test for select previous scope (#2717)
With our latest performance updates there is a clear difference in performance between containing and relative scopes. To keep track of this I have added relative scopes to the performance tests. I also added a few tests for every scope. ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [/] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [/] I have not broken the cheatsheet
1 parent d8287e6 commit 6c4c02a

File tree

1 file changed

+70
-30
lines changed

1 file changed

+70
-30
lines changed

packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
asyncSafety,
33
type ActionDescriptor,
4+
type Modifier,
45
type ScopeType,
56
type SimpleScopeTypeType,
67
} from "@cursorless/common";
@@ -11,9 +12,10 @@ import { endToEndTestSetup } from "../endToEndTestSetup";
1112

1213
const testData = generateTestData(100);
1314

14-
const textBasedThresholdMs = 100;
15-
const parseTreeThresholdMs = 500;
16-
const surroundingPairThresholdMs = 500;
15+
const smallThresholdMs = 100;
16+
const largeThresholdMs = 500;
17+
18+
type ModifierType = "containing" | "previous" | "every";
1719

1820
suite("Performance", async function () {
1921
endToEndTestSetup(this);
@@ -32,42 +34,56 @@ suite("Performance", async function () {
3234

3335
test(
3436
"Remove token",
35-
asyncSafety(() => removeToken(textBasedThresholdMs)),
37+
asyncSafety(() => removeToken(smallThresholdMs)),
3638
);
3739

38-
const fixtures: [SimpleScopeTypeType | ScopeType, number][] = [
40+
const fixtures: (
41+
| [SimpleScopeTypeType | ScopeType, number]
42+
| [SimpleScopeTypeType | ScopeType, number, ModifierType]
43+
)[] = [
3944
// Text based
40-
["character", textBasedThresholdMs],
41-
["word", textBasedThresholdMs],
42-
["token", textBasedThresholdMs],
43-
["identifier", textBasedThresholdMs],
44-
["line", textBasedThresholdMs],
45-
["sentence", textBasedThresholdMs],
46-
["paragraph", textBasedThresholdMs],
47-
["document", textBasedThresholdMs],
48-
["nonWhitespaceSequence", textBasedThresholdMs],
49-
// Parse tree based
50-
["string", parseTreeThresholdMs],
51-
["map", parseTreeThresholdMs],
52-
["collectionKey", parseTreeThresholdMs],
53-
["value", parseTreeThresholdMs],
45+
["character", smallThresholdMs],
46+
["word", smallThresholdMs],
47+
["token", smallThresholdMs],
48+
["identifier", smallThresholdMs],
49+
["line", smallThresholdMs],
50+
["sentence", smallThresholdMs],
51+
["paragraph", smallThresholdMs],
52+
["document", smallThresholdMs],
53+
["nonWhitespaceSequence", smallThresholdMs],
54+
// Parse tree based, containing/every scope
55+
["string", smallThresholdMs],
56+
["map", smallThresholdMs],
57+
["collectionKey", smallThresholdMs],
58+
["value", smallThresholdMs],
59+
["collectionKey", smallThresholdMs, "every"],
60+
["value", smallThresholdMs, "every"],
61+
// Parse tree based, relative scope
62+
["collectionKey", largeThresholdMs, "previous"],
63+
["value", largeThresholdMs, "previous"],
5464
// Text based, but utilizes surrounding pair
55-
["boundedParagraph", surroundingPairThresholdMs],
56-
["boundedNonWhitespaceSequence", surroundingPairThresholdMs],
57-
["collectionItem", surroundingPairThresholdMs],
65+
["boundedParagraph", largeThresholdMs],
66+
["boundedNonWhitespaceSequence", largeThresholdMs],
67+
["collectionItem", largeThresholdMs],
5868
// Surrounding pair
59-
[{ type: "surroundingPair", delimiter: "any" }, surroundingPairThresholdMs],
69+
[{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs],
70+
[{ type: "surroundingPair", delimiter: "curlyBrackets" }, largeThresholdMs],
71+
[{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs, "every"],
6072
[
61-
{ type: "surroundingPair", delimiter: "curlyBrackets" },
62-
surroundingPairThresholdMs,
73+
{ type: "surroundingPair", delimiter: "any" },
74+
largeThresholdMs,
75+
"previous",
6376
],
6477
];
6578

66-
for (const [scope, threshold] of fixtures) {
67-
const [scopeType, title] = getScopeTypeAndTitle(scope);
79+
for (const [scope, threshold, modifierType] of fixtures) {
80+
const [scopeType, scopeTitle] = getScopeTypeAndTitle(scope);
81+
const title = modifierType
82+
? `${modifierType} ${scopeTitle}`
83+
: `${scopeTitle}`;
6884
test(
6985
`Select ${title}`,
70-
asyncSafety(() => selectScopeType(scopeType, threshold)),
86+
asyncSafety(() => selectScopeType(scopeType, threshold, modifierType)),
7187
);
7288
}
7389
});
@@ -82,16 +98,40 @@ async function removeToken(thresholdMs: number) {
8298
});
8399
}
84100

85-
async function selectScopeType(scopeType: ScopeType, thresholdMs: number) {
101+
async function selectScopeType(
102+
scopeType: ScopeType,
103+
thresholdMs: number,
104+
modifierType?: ModifierType,
105+
) {
86106
await testPerformance(thresholdMs, {
87107
name: "setSelection",
88108
target: {
89109
type: "primitive",
90-
modifiers: [{ type: "containingScope", scopeType }],
110+
modifiers: [getModifier(scopeType, modifierType)],
91111
},
92112
});
93113
}
94114

115+
function getModifier(
116+
scopeType: ScopeType,
117+
modifierType: ModifierType = "containing",
118+
): Modifier {
119+
switch (modifierType) {
120+
case "containing":
121+
return { type: "containingScope", scopeType };
122+
case "every":
123+
return { type: "everyScope", scopeType };
124+
case "previous":
125+
return {
126+
type: "relativeScope",
127+
direction: "backward",
128+
offset: 1,
129+
length: 1,
130+
scopeType,
131+
};
132+
}
133+
}
134+
95135
async function testPerformance(thresholdMs: number, action: ActionDescriptor) {
96136
const editor = await openNewEditor(testData, { languageId: "json" });
97137
// This is the position of the last json key in the document

0 commit comments

Comments
 (0)