cloudflare / cloudflare/capnweb

memory leak on client side with websocket sessions

Open
#153 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
4k
Forks
143
Avg merge
4d 6h
Merged PRs (30d)
7

Description

There seems to be a memory leak on the client side with websocket sessions, unless I am doing something wrong. I understand there are disposal rules to consider, especially with websockets per the docs, but I tried many different things and the only way to clear the memory of unused promises seems to be to restart the session. See the reproduction below.

I also ran it with `--inspect` and it seems there are forever-growing `Promise`'s kept in the memory.

## Server:
```ts
import { RpcTarget, newWebSocketRpcSession } from "capnweb";
import { WebSocketServer } from "ws";

class Api extends RpcTarget {
sendMeText(text: string): string {
return `got: ${text}`;
}
}

const server = new WebSocketServer({ port: 8787, perMessageDeflate: false });

server.on("connection", ws => {
newWebSocketRpcSession(ws as any, new Api());
});

console.log("ws://localhost:8787");
```

## Client:
```ts
import { newWebSocketRpcSession } from "capnweb";

type Api = {
sendMeText(text: string): string;
};

const session = newWebSocketRpcSession("ws://localhost:8787");
const text = "abc123".repeat(2000);

let calls = 0;

setInterval(() => {
console.log(
`calls=${calls} heapUsed=${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(1)}MB`
);
}, 1000);

while (true) {
await session.sendMeText(text);
++calls;
await new Promise(resolve => setTimeout(resolve, 1)); // delay 1ms
}

// this doesn't prevent a memory leak either, same result:
while(true){
const res = session.sendMeText(text);
await res;
res[Symbol.dispose]();
++calls;
await new Promise(resolve => setTimeout(resolve, 1)); // delay 1ms
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.