Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/scripts/chat-simulation/fixtures/_chatperf_async.ts
13383 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
// perf-benchmark-marker
7
8
/**
9
* Fixture for chat-simulation benchmarks.
10
* Simplified from src/vs/base/common/async.ts for stable perf testing.
11
*/
12
13
import { IDisposable } from './lifecycle';
14
import { CancellationError } from './errors';
15
16
export class Throttler {
17
private activePromise: Promise<any> | null = null;
18
private queuedPromiseFactory: (() => Promise<any>) | null = null;
19
20
queue<T>(promiseFactory: () => Promise<T>): Promise<T> {
21
if (this.activePromise) {
22
this.queuedPromiseFactory = promiseFactory;
23
return this.activePromise as Promise<T>;
24
}
25
this.activePromise = promiseFactory();
26
return this.activePromise.finally(() => {
27
this.activePromise = null;
28
if (this.queuedPromiseFactory) {
29
const factory = this.queuedPromiseFactory;
30
this.queuedPromiseFactory = null;
31
return this.queue(factory);
32
}
33
});
34
}
35
}
36
37
export class Delayer<T> implements IDisposable {
38
private timeout: any;
39
private task: (() => T | Promise<T>) | null = null;
40
41
constructor(public defaultDelay: number) { }
42
43
trigger(task: () => T | Promise<T>, delay: number = this.defaultDelay): Promise<T> {
44
this.task = task;
45
this.cancelTimeout();
46
return new Promise<T>((resolve, reject) => {
47
this.timeout = setTimeout(() => {
48
this.timeout = null;
49
try { resolve(this.task!()); } catch (e) { reject(e); }
50
this.task = null;
51
}, delay);
52
});
53
}
54
55
private cancelTimeout(): void {
56
if (this.timeout !== null) {
57
clearTimeout(this.timeout);
58
this.timeout = null;
59
}
60
}
61
62
dispose(): void {
63
this.cancelTimeout();
64
}
65
}
66
67
export class RunOnceScheduler implements IDisposable {
68
private runner: (() => void) | null;
69
private timeout: any;
70
71
constructor(runner: () => void, private delay: number) {
72
this.runner = runner;
73
}
74
75
schedule(delay = this.delay): void {
76
this.cancel();
77
this.timeout = setTimeout(() => {
78
this.timeout = null;
79
this.runner?.();
80
}, delay);
81
}
82
83
cancel(): void {
84
if (this.timeout !== null) {
85
clearTimeout(this.timeout);
86
this.timeout = null;
87
}
88
}
89
90
isScheduled(): boolean { return this.timeout !== null; }
91
92
dispose(): void {
93
this.cancel();
94
this.runner = null;
95
}
96
}
97
98
export class Queue<T> {
99
private readonly queue: Array<() => Promise<T>> = [];
100
private running = false;
101
102
async enqueue(factory: () => Promise<T>): Promise<T> {
103
return new Promise<T>((resolve, reject) => {
104
this.queue.push(() => factory().then(resolve, reject));
105
if (!this.running) { this.processQueue(); }
106
});
107
}
108
109
private async processQueue(): Promise<void> {
110
this.running = true;
111
while (this.queue.length > 0) {
112
const task = this.queue.shift()!;
113
await task();
114
}
115
this.running = false;
116
}
117
118
get size(): number { return this.queue.length; }
119
}
120
121
export function timeout(millis: number): Promise<void> {
122
return new Promise<void>(resolve => setTimeout(resolve, millis));
123
}
124
125
export async function retry<T>(task: () => Promise<T>, delay: number, retries: number): Promise<T> {
126
let lastError: Error | undefined;
127
for (let i = 0; i < retries; i++) {
128
try { return await task(); }
129
catch (error) { lastError = error as Error; await timeout(delay); }
130
}
131
throw lastError;
132
}
133
134