Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions tests/perf/_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,17 @@ export class MockInfoTransport implements IRequestTransport {
* Server-to-client frames are injected with {@linkcode MockWebSocket.serverSend}.
*/
export class MockWebSocket extends EventTarget {
static instances: MockWebSocket[] = [];
/**
* The most recently constructed instance, which is all {@linkcode lastMockWebSocket} ever needs.
*
* Deliberately a single reference rather than a list: scenarios that build a transport per
* sample would otherwise pile every socket — and, through the listeners registered on it, every
* transport and its keep-alive timers — into a static array that nothing releases until the
* scenario ends. That turns a per-sample measurement into a function of how many samples have
* already run, and leaves enough retained garbage that whether a major GC lands inside the
* measured window changes the result.
*/
static last: MockWebSocket | undefined;

readonly url: string;
binaryType: BinaryType = "blob";
Expand All @@ -114,7 +124,7 @@ export class MockWebSocket extends EventTarget {
constructor(url: string | URL, _protocols?: string | string[]) {
super();
this.url = String(url);
MockWebSocket.instances.push(this);
MockWebSocket.last = this;
queueMicrotask(() => {
if (this.readyState !== 0) return;
this.readyState = 1; // OPEN
Expand Down Expand Up @@ -170,7 +180,7 @@ const OriginalWebSocket: typeof globalThis.WebSocket = globalThis.WebSocket;

/** Replaces `globalThis.WebSocket` with {@linkcode MockWebSocket} (picked up by `ReconnectingWebSocket`). */
export function installMockWebSocket(): void {
MockWebSocket.instances = [];
MockWebSocket.last = undefined;
// The mock implements only what the transport touches, so it is not structurally a
// `WebSocket`; the double assertion is the whole point of installing a stand-in.
globalThis.WebSocket = MockWebSocket as unknown as typeof globalThis.WebSocket;
Expand All @@ -183,7 +193,7 @@ export function restoreWebSocket(): void {

/** Returns the most recently created {@linkcode MockWebSocket} (i.e. the one backing the transport). */
export function lastMockWebSocket(): MockWebSocket {
const socket = MockWebSocket.instances.at(-1);
const socket = MockWebSocket.last;
if (!socket) throw new Error("No MockWebSocket instance was created");
return socket;
}
2 changes: 1 addition & 1 deletion tests/perf/scenarios/user_account_channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ scenario({
"for one user — the calls a feed makes at session start and on every reconnect",
unit: "subscription",
unitsPerIteration: 3,
iterations: 1,
iterations: 20,
samples: 25,
warmupSamples: 3,
setup: () => {
Expand Down
Loading