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