From d5df49157caa9ac79dadee50d4e805a8cef6dad3 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 11 Jan 2025 07:38:04 +0100 Subject: [PATCH 1/5] Added performance test for `select previous scope` --- .../src/suite/performance.vscode.test.ts | 95 +++++++++++++------ 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts index 010a63897b..7932e96c2e 100644 --- a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts @@ -1,6 +1,7 @@ import { asyncSafety, type ActionDescriptor, + type Modifier, type ScopeType, type SimpleScopeTypeType, } from "@cursorless/common"; @@ -11,9 +12,10 @@ import { endToEndTestSetup } from "../endToEndTestSetup"; const testData = generateTestData(100); -const textBasedThresholdMs = 100; -const parseTreeThresholdMs = 500; -const surroundingPairThresholdMs = 500; +const smallThresholdMs = 100; +const largeThresholdMs = 500; + +type ModifierType = "previous"; suite("Performance", async function () { endToEndTestSetup(this); @@ -32,42 +34,53 @@ suite("Performance", async function () { test( "Remove token", - asyncSafety(() => removeToken(textBasedThresholdMs)), + asyncSafety(() => removeToken(smallThresholdMs)), ); - const fixtures: [SimpleScopeTypeType | ScopeType, number][] = [ + const fixtures: ( + | [SimpleScopeTypeType | ScopeType, number] + | [SimpleScopeTypeType | ScopeType, number, ModifierType] + )[] = [ // Text based - ["character", textBasedThresholdMs], - ["word", textBasedThresholdMs], - ["token", textBasedThresholdMs], - ["identifier", textBasedThresholdMs], - ["line", textBasedThresholdMs], - ["sentence", textBasedThresholdMs], - ["paragraph", textBasedThresholdMs], - ["document", textBasedThresholdMs], - ["nonWhitespaceSequence", textBasedThresholdMs], - // Parse tree based - ["string", parseTreeThresholdMs], - ["map", parseTreeThresholdMs], - ["collectionKey", parseTreeThresholdMs], - ["value", parseTreeThresholdMs], + ["character", smallThresholdMs], + ["word", smallThresholdMs], + ["token", smallThresholdMs], + ["identifier", smallThresholdMs], + ["line", smallThresholdMs], + ["sentence", smallThresholdMs], + ["paragraph", smallThresholdMs], + ["document", smallThresholdMs], + ["nonWhitespaceSequence", smallThresholdMs], + // Parse tree based, containing scope + ["string", smallThresholdMs], + ["map", smallThresholdMs], + ["collectionKey", smallThresholdMs], + ["value", smallThresholdMs], + // Parse tree based, relative scope + ["collectionKey", largeThresholdMs, "previous"], + ["value", largeThresholdMs, "previous"], // Text based, but utilizes surrounding pair - ["boundedParagraph", surroundingPairThresholdMs], - ["boundedNonWhitespaceSequence", surroundingPairThresholdMs], - ["collectionItem", surroundingPairThresholdMs], + ["boundedParagraph", largeThresholdMs], + ["boundedNonWhitespaceSequence", largeThresholdMs], + ["collectionItem", largeThresholdMs], // Surrounding pair - [{ type: "surroundingPair", delimiter: "any" }, surroundingPairThresholdMs], + [{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs], + [{ type: "surroundingPair", delimiter: "curlyBrackets" }, largeThresholdMs], [ - { type: "surroundingPair", delimiter: "curlyBrackets" }, - surroundingPairThresholdMs, + { type: "surroundingPair", delimiter: "any" }, + largeThresholdMs, + "previous", ], ]; - for (const [scope, threshold] of fixtures) { - const [scopeType, title] = getScopeTypeAndTitle(scope); + for (const [scope, threshold, modifierType] of fixtures) { + const [scopeType, scopeTitle] = getScopeTypeAndTitle(scope); + const title = modifierType + ? `${modifierType} ${scopeTitle}` + : `${scopeTitle}`; test( `Select ${title}`, - asyncSafety(() => selectScopeType(scopeType, threshold)), + asyncSafety(() => selectScopeType(scopeType, threshold, modifierType)), ); } }); @@ -82,16 +95,38 @@ async function removeToken(thresholdMs: number) { }); } -async function selectScopeType(scopeType: ScopeType, thresholdMs: number) { +async function selectScopeType( + scopeType: ScopeType, + thresholdMs: number, + modifierType?: ModifierType, +) { await testPerformance(thresholdMs, { name: "setSelection", target: { type: "primitive", - modifiers: [{ type: "containingScope", scopeType }], + modifiers: [getModifier(scopeType, modifierType)], }, }); } +function getModifier( + scopeType: ScopeType, + modifierType?: ModifierType, +): Modifier { + switch (modifierType) { + case "previous": + return { + type: "relativeScope", + direction: "backward", + offset: 1, + length: 1, + scopeType, + }; + default: + return { type: "containingScope", scopeType }; + } +} + async function testPerformance(thresholdMs: number, action: ActionDescriptor) { const editor = await openNewEditor(testData, { languageId: "json" }); // This is the position of the last json key in the document From 087470361e9c27dd25318d41d542a9feda9d1d50 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 11 Jan 2025 07:43:10 +0100 Subject: [PATCH 2/5] Added every scopes --- .../src/suite/performance.vscode.test.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts index 7932e96c2e..36f4301800 100644 --- a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts @@ -15,7 +15,7 @@ const testData = generateTestData(100); const smallThresholdMs = 100; const largeThresholdMs = 500; -type ModifierType = "previous"; +type ModifierType = "containing" | "previous" | "every"; suite("Performance", async function () { endToEndTestSetup(this); @@ -59,6 +59,8 @@ suite("Performance", async function () { // Parse tree based, relative scope ["collectionKey", largeThresholdMs, "previous"], ["value", largeThresholdMs, "previous"], + ["collectionKey", largeThresholdMs, "every"], + ["value", largeThresholdMs, "every"], // Text based, but utilizes surrounding pair ["boundedParagraph", largeThresholdMs], ["boundedNonWhitespaceSequence", largeThresholdMs], @@ -71,6 +73,7 @@ suite("Performance", async function () { largeThresholdMs, "previous", ], + [{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs, "every"], ]; for (const [scope, threshold, modifierType] of fixtures) { @@ -98,7 +101,7 @@ async function removeToken(thresholdMs: number) { async function selectScopeType( scopeType: ScopeType, thresholdMs: number, - modifierType?: ModifierType, + modifierType: ModifierType = "containing", ) { await testPerformance(thresholdMs, { name: "setSelection", @@ -111,9 +114,13 @@ async function selectScopeType( function getModifier( scopeType: ScopeType, - modifierType?: ModifierType, + modifierType: ModifierType, ): Modifier { switch (modifierType) { + case "containing": + return { type: "containingScope", scopeType }; + case "every": + return { type: "everyScope", scopeType }; case "previous": return { type: "relativeScope", @@ -122,8 +129,6 @@ function getModifier( length: 1, scopeType, }; - default: - return { type: "containingScope", scopeType }; } } From 9c358793df77b48fc0055e1f65a9f48468981062 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 11 Jan 2025 07:44:36 +0100 Subject: [PATCH 3/5] Clean up --- .../src/suite/performance.vscode.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts index 36f4301800..c583af3f20 100644 --- a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts @@ -101,7 +101,7 @@ async function removeToken(thresholdMs: number) { async function selectScopeType( scopeType: ScopeType, thresholdMs: number, - modifierType: ModifierType = "containing", + modifierType?: ModifierType, ) { await testPerformance(thresholdMs, { name: "setSelection", @@ -114,7 +114,7 @@ async function selectScopeType( function getModifier( scopeType: ScopeType, - modifierType: ModifierType, + modifierType: ModifierType = "containing", ): Modifier { switch (modifierType) { case "containing": From ae55d141bbfc888743f4689532f6af2019a9cb84 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 11 Jan 2025 08:01:05 +0100 Subject: [PATCH 4/5] Update every threshold --- .../src/suite/performance.vscode.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts index c583af3f20..07cf18ac63 100644 --- a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts @@ -51,16 +51,16 @@ suite("Performance", async function () { ["paragraph", smallThresholdMs], ["document", smallThresholdMs], ["nonWhitespaceSequence", smallThresholdMs], - // Parse tree based, containing scope + // Parse tree based, containing/every scope ["string", smallThresholdMs], ["map", smallThresholdMs], ["collectionKey", smallThresholdMs], ["value", smallThresholdMs], + ["collectionKey", smallThresholdMs, "every"], + ["value", smallThresholdMs, "every"], // Parse tree based, relative scope ["collectionKey", largeThresholdMs, "previous"], ["value", largeThresholdMs, "previous"], - ["collectionKey", largeThresholdMs, "every"], - ["value", largeThresholdMs, "every"], // Text based, but utilizes surrounding pair ["boundedParagraph", largeThresholdMs], ["boundedNonWhitespaceSequence", largeThresholdMs], From b961f6e1904c22dfd3c4ca8d09918c7f1ccf1165 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 11 Jan 2025 08:01:54 +0100 Subject: [PATCH 5/5] Update order --- .../cursorless-vscode-e2e/src/suite/performance.vscode.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts index 07cf18ac63..c8dc572507 100644 --- a/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/performance.vscode.test.ts @@ -68,12 +68,12 @@ suite("Performance", async function () { // Surrounding pair [{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs], [{ type: "surroundingPair", delimiter: "curlyBrackets" }, largeThresholdMs], + [{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs, "every"], [ { type: "surroundingPair", delimiter: "any" }, largeThresholdMs, "previous", ], - [{ type: "surroundingPair", delimiter: "any" }, largeThresholdMs, "every"], ]; for (const [scope, threshold, modifierType] of fixtures) {