Path: blob/main/extensions/copilot/src/util/common/performance.ts
13397 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45interface IMonacoPerformanceMarks {6mark(name: string, markOptions?: { startTime?: number }): void;7getMarks(): { name: string; startTime: number }[];8clearMarks(name?: string): void;9}1011function _getNativePolyfill(): IMonacoPerformanceMarks {12return {13mark: (name, markOptions) => performance.mark(name, markOptions),14getMarks: () => performance.getEntries().filter(e => e.entryType === 'mark').map(e => ({ name: e.name, startTime: e.startTime })),15clearMarks: name => {16performance.clearMarks(name);17},18};19}2021const perf: IMonacoPerformanceMarks = (globalThis as { MonacoPerformanceMarks?: IMonacoPerformanceMarks }).MonacoPerformanceMarks ?? _getNativePolyfill();2223const chatExtPrefix = 'code/chat/ext/';2425/** Tracks all mark names emitted per session so they can be cleared individually. */26const chatExtMarksBySession = new Map<string, Set<string>>();2728/**29* Well-defined perf marks for the chat extension request lifecycle.30* Each mark is a boundary of a measurable scenario — don't add marks31* without defining what scenario they belong to.32*33* These marks live inside the vscode-side `agent/willInvoke` → `agent/didInvoke`34* window and break down what happens in the extension during a chat request.35*36* ## Per-Session Scenarios (scoped by sessionId via {@link markChatExt})37*38* **Extension Handler Duration** — total time in the participant handler:39* `willHandleParticipant` → `didHandleParticipant`40* Corresponds to vscode's `agent/willInvoke` → `agent/didInvoke`.41*42* **Prompt Build Time** — context gathering and prompt assembly (per turn):43* `willBuildPrompt` → `didBuildPrompt`44* If this is slow, context resolution (workspace search, file reads, instructions) is the bottleneck.45*46* **LLM Fetch Time** — network round-trip to the language model (per turn):47* `willFetch` → `didFetch`48* If this is slow, model latency or network is the bottleneck.49*50* ## One-Time Activation Scenarios (global marks, not request-scoped)51*52* **Extension Activation Duration** — cold-start time:53* `code/chat/ext/willActivate` → `code/chat/ext/didActivate`54*55* **Copilot Token Wait** — authentication readiness blocking activation:56* `code/chat/ext/willWaitForCopilotToken` → `code/chat/ext/didWaitForCopilotToken`57*/58export const ChatExtPerfMark = {59/** Chat participant handler starts */60WillHandleParticipant: 'willHandleParticipant',61/** Chat participant handler completes */62DidHandleParticipant: 'didHandleParticipant',63/** Prompt building starts (per turn) */64WillBuildPrompt: 'willBuildPrompt',65/** Prompt building completes (per turn) */66DidBuildPrompt: 'didBuildPrompt',67/** LLM fetch starts (per turn) */68WillFetch: 'willFetch',69/** LLM fetch completes (per turn) */70DidFetch: 'didFetch',71} as const;7273export type ChatExtPerfMarkName = typeof ChatExtPerfMark[keyof typeof ChatExtPerfMark];7475/**76* Emits a performance mark scoped to a chat session:77* `code/chat/ext/<sessionId>/<name>`78*79* Marks persist in the extension host process until explicitly cleared80* via {@link clearChatExtMarks}.81*/82export function markChatExt(sessionId: string | undefined, name: ChatExtPerfMarkName): void {83if (sessionId) {84const fullName = `${chatExtPrefix}${sessionId}/${name}`;85let names = chatExtMarksBySession.get(sessionId);86if (!names) {87names = new Set();88chatExtMarksBySession.set(sessionId, names);89}90names.add(fullName);91perf.mark(fullName);92}93}9495/**96* Clears all performance marks for the given chat session.97*/98export function clearChatExtMarks(sessionId: string): void {99const names = chatExtMarksBySession.get(sessionId);100if (names) {101for (const name of names) {102perf.clearMarks(name);103}104chatExtMarksBySession.delete(sessionId);105}106}107108export const ChatExtGlobalPerfMark = {109/** Extension activation starts */110WillActivate: 'willActivate',111/** Extension activation completes */112DidActivate: 'didActivate',113/** Waiting for Copilot token starts */114WillWaitForCopilotToken: 'willWaitForCopilotToken',115/** Copilot token received */116DidWaitForCopilotToken: 'didWaitForCopilotToken',117} as const;118119export type ChatExtGlobalPerfMarkName = typeof ChatExtGlobalPerfMark[keyof typeof ChatExtGlobalPerfMark];120121/**122* Emits a global (non-session-scoped) performance mark:123* `code/chat/ext/<name>`124*125* Used for one-time activation marks like `willActivate` / `didActivate`.126*/127export function markChatExtGlobal(name: ChatExtGlobalPerfMarkName): void {128perf.mark(`${chatExtPrefix}${name}`);129}130131/**132* Returns all marks currently stored in the polyfill.133* Useful for tests and diagnostics.134*/135export function getChatExtMarks(): { name: string; startTime: number }[] {136return perf.getMarks();137}138139140