Unified · Split
| @@ -83,6 +83,7 @@ jobs: · 82 unmodified lines | ||
| 83 | 83 | # Terminal PTY scripting is flaky in CI VMs; renderer perf checks remain enforced. |
| 84 | 84 | T3CODE_DESKTOP_PERF_RUN_TERMINAL: "0" |
| 85 | 85 | T3CODE_DESKTOP_PERF_RUN_OPTIONAL_RENDERER: "0" |
| 86 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: "0" | |
| 86 | 87 | T3CODE_DESKTOP_PERF_BENCHMARK_FOLLOW_UP_PASSES: "0" |
| 87 | 88 | T3CODE_ELECTRON_STARTUP_TIMEOUT_MS: "180000" |
| 88 | 89 | run: xvfb-run -a bun run test:desktop-perf |
| @@ -95,6 +96,7 @@ jobs: · 6 unmodified lines | ||
| 95 | 96 | T3CODE_PERF_MAX_LONG_DISPATCH_COUNT: "5" |
| 96 | 97 | T3CODE_DESKTOP_PERF_RUN_TERMINAL: "0" |
| 97 | 98 | T3CODE_DESKTOP_PERF_RUN_OPTIONAL_RENDERER: "0" |
| 99 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: "0" | |
| 98 | 100 | T3CODE_DESKTOP_PERF_BENCHMARK_FOLLOW_UP_PASSES: "0" |
| 99 | 101 | T3CODE_ELECTRON_STARTUP_TIMEOUT_MS: "180000" |
| 100 | 102 | run: xvfb-run -a bun run test:desktop-perf |
| @@ -108,6 +110,7 @@ jobs: · 7 unmodified lines | ||
| 108 | 110 | T3CODE_PERF_MAX_LONG_DISPATCH_COUNT: "5" |
| 109 | 111 | T3CODE_DESKTOP_PERF_RUN_TERMINAL: "0" |
| 110 | 112 | T3CODE_DESKTOP_PERF_RUN_OPTIONAL_RENDERER: "0" |
| 113 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: "0" | |
| 111 | 114 | T3CODE_DESKTOP_PERF_BENCHMARK_FOLLOW_UP_PASSES: "0" |
| 112 | 115 | T3CODE_ELECTRON_STARTUP_TIMEOUT_MS: "180000" |
| 113 | 116 | run: xvfb-run -a bun run test:desktop-perf:post |
| @@ -6,6 +6,7 @@ import path from "node:path"; · 5 unmodified lines | ||
| 6 | 6 | import { BrowserWindow, contentTracing, type WebContents } from "electron"; |
| 7 | 7 | import { |
| 8 | 8 | resolveBenchmarkFollowUpPassCount, |
| 9 | + shouldRunBenchmarkThreadSweep, | |
| 9 | 10 | shouldRunOptionalRendererPerfInteractions, |
| 10 | 11 | shouldRunTerminalPerfInteractions, |
| 11 | 12 | } from "./perfConfig"; |
| @@ -27,6 +28,10 @@ const BENCHMARK_FOLLOW_UP_PASS_COUNT = resolveBenchmarkFollowUpPassCount({ · 15 unmodified lines | ||
| 27 | 28 | process.env.T3CODE_DESKTOP_PERF_BENCHMARK_FOLLOW_UP_PASSES, |
| 28 | 29 | CI: process.env.CI, |
| 29 | 30 | }); |
| 31 | +const RUN_BENCHMARK_THREAD_SWEEP = shouldRunBenchmarkThreadSweep({ | |
| 32 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: process.env.T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP, | |
| 33 | + CI: process.env.CI, | |
| 34 | +}); | |
| 30 | 35 | |
| 31 | 36 | function delay(ms: number): Promise<void> { |
| 32 | 37 | return new Promise((resolve) => setTimeout(resolve, ms)); |
| @@ -575,13 +580,14 @@ async function runRendererPerfInteractions( · 542 unmodified lines | ||
| 575 | 580 | return Number((sorted[middle] ?? 0).toFixed(2)); |
| 576 | 581 | }; |
| 577 | 582 | |
| 583 | + const runBenchmarkThreadSweep = ${RUN_BENCHMARK_THREAD_SWEEP}; | |
| 578 | 584 | const preferredThreadIds = ${JSON.stringify(benchmarkThreadIds)}.filter( |
| 579 | 585 | (value) => typeof value === "string" && value.length > 0, |
| 580 | 586 | ); |
| 581 | − const benchmarkThreadIds = preferredThreadIds.filter((threadId) => | |
| 582 | − renderedThreadIds.includes(threadId), | |
| 583 | − ); | |
| 584 | − if (benchmarkThreadIds.length === 0) { | |
| 587 | + const benchmarkThreadIds = runBenchmarkThreadSweep | |
| 588 | + ? preferredThreadIds.filter((threadId) => renderedThreadIds.includes(threadId)) | |
| 589 | + : []; | |
| 590 | + if (runBenchmarkThreadSweep && benchmarkThreadIds.length === 0) { | |
| 585 | 591 | benchmarkThreadIds.push(...renderedThreadIds.slice(0, ${BENCHMARK_THREAD_COUNT})); |
| 586 | 592 | } |
| 587 | 593 | |
| @@ -599,25 +605,27 @@ async function runRendererPerfInteractions( · 11 unmodified lines | ||
| 599 | 605 | }; |
| 600 | 606 | |
| 601 | 607 | const firstPassByThreadId = new Map(); |
| 602 | − for (const threadId of benchmarkThreadIds) { | |
| 603 | − await ensureThreadSwitchTarget(threadId); | |
| 604 | − firstPassByThreadId.set(threadId, await measureThreadRender(threadId)); | |
| 605 | − } | |
| 606 | − | |
| 607 | 608 | const followUpSamplesByThreadId = new Map(); |
| 608 | − for (const threadId of benchmarkThreadIds) { | |
| 609 | − followUpSamplesByThreadId.set(threadId, []); | |
| 610 | − } | |
| 611 | − const followUpPassCount = ${BENCHMARK_FOLLOW_UP_PASS_COUNT}; | |
| 612 | − for (let passIndex = 0; passIndex < followUpPassCount; passIndex += 1) { | |
| 609 | + if (runBenchmarkThreadSweep) { | |
| 613 | 610 | for (const threadId of benchmarkThreadIds) { |
| 614 | 611 | await ensureThreadSwitchTarget(threadId); |
| 615 | − const sample = await measureThreadRender(threadId); | |
| 616 | − const samples = followUpSamplesByThreadId.get(threadId); | |
| 617 | − if (Array.isArray(samples)) { | |
| 618 | − samples.push(sample.renderMs); | |
| 619 | − } else { | |
| 620 | − followUpSamplesByThreadId.set(threadId, [sample.renderMs]); | |
| 612 | + firstPassByThreadId.set(threadId, await measureThreadRender(threadId)); | |
| 613 | + } | |
| 614 | + | |
| 615 | + for (const threadId of benchmarkThreadIds) { | |
| 616 | + followUpSamplesByThreadId.set(threadId, []); | |
| 617 | + } | |
| 618 | + const followUpPassCount = ${BENCHMARK_FOLLOW_UP_PASS_COUNT}; | |
| 619 | + for (let passIndex = 0; passIndex < followUpPassCount; passIndex += 1) { | |
| 620 | + for (const threadId of benchmarkThreadIds) { | |
| 621 | + await ensureThreadSwitchTarget(threadId); | |
| 622 | + const sample = await measureThreadRender(threadId); | |
| 623 | + const samples = followUpSamplesByThreadId.get(threadId); | |
| 624 | + if (Array.isArray(samples)) { | |
| 625 | + samples.push(sample.renderMs); | |
| 626 | + } else { | |
| 627 | + followUpSamplesByThreadId.set(threadId, [sample.renderMs]); | |
| 628 | + } | |
| 621 | 629 | } |
| 622 | 630 | } |
| 623 | 631 | } |
| @@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest"; · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | import { |
| 4 | 4 | resolveBenchmarkFollowUpPassCount, |
| 5 | + shouldRunBenchmarkThreadSweep, | |
| 5 | 6 | shouldRunOptionalRendererPerfInteractions, |
| 6 | 7 | shouldRunTerminalPerfInteractions, |
| 7 | 8 | } from "./perfConfig"; |
| @@ -207,3 +208,25 @@ describe("shouldRunOptionalRendererPerfInteractions", () => { · 199 unmodified lines | ||
| 207 | 208 | ).toBe(false); |
| 208 | 209 | }); |
| 209 | 210 | }); |
| 211 | + | |
| 212 | +describe("shouldRunBenchmarkThreadSweep", () => { | |
| 213 | + it("defaults to enabled outside CI and disabled in CI", () => { | |
| 214 | + expect(shouldRunBenchmarkThreadSweep({ CI: "false" })).toBe(true); | |
| 215 | + expect(shouldRunBenchmarkThreadSweep({ CI: "true" })).toBe(false); | |
| 216 | + }); | |
| 217 | + | |
| 218 | + it("supports explicit env overrides", () => { | |
| 219 | + expect( | |
| 220 | + shouldRunBenchmarkThreadSweep({ | |
| 221 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: "1", | |
| 222 | + CI: "true", | |
| 223 | + }), | |
| 224 | + ).toBe(true); | |
| 225 | + expect( | |
| 226 | + shouldRunBenchmarkThreadSweep({ | |
| 227 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP: "off", | |
| 228 | + CI: "false", | |
| 229 | + }), | |
| 230 | + ).toBe(false); | |
| 231 | + }); | |
| 232 | +}); | |
| @@ -13,6 +13,11 @@ type PerfBenchmarkEnv = { · 12 unmodified lines | ||
| 13 | 13 | CI?: string | undefined; |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | +type BenchmarkSweepToggleEnv = { | |
| 17 | + T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP?: string | undefined; | |
| 18 | + CI?: string | undefined; | |
| 19 | +}; | |
| 20 | + | |
| 16 | 21 | const TRUE_VALUES = new Set(["1", "true", "yes", "on"]); |
| 17 | 22 | const FALSE_VALUES = new Set(["0", "false", "no", "off"]); |
| 18 | 23 | const MAX_BENCHMARK_FOLLOW_UP_PASSES = 5; |
| @@ -52,6 +57,12 @@ export function shouldRunOptionalRendererPerfInteractions(env: OptionalRendererT · 33 unmodified lines | ||
| 52 | 57 | return !isCiEnvironment(env.CI); |
| 53 | 58 | } |
| 54 | 59 | |
| 60 | +export function shouldRunBenchmarkThreadSweep(env: BenchmarkSweepToggleEnv): boolean { | |
| 61 | + const toggleOverride = parseBooleanLike(env.T3CODE_DESKTOP_PERF_RUN_BENCHMARK_SWEEP); | |
| 62 | + if (toggleOverride !== null) return toggleOverride; | |
| 63 | + return !isCiEnvironment(env.CI); | |
| 64 | +} | |
| 65 | + | |
| 55 | 66 | export function resolveBenchmarkFollowUpPassCount(env: PerfBenchmarkEnv): number { |
| 56 | 67 | const raw = env.T3CODE_DESKTOP_PERF_BENCHMARK_FOLLOW_UP_PASSES?.trim(); |
| 57 | 68 | if (raw && /^\d+$/.test(raw)) { |