Skip to content

Memory leak on client side with websocket sessions #153

@VastBlast

Description

@VastBlast

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:

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:

import { newWebSocketRpcSession } from "capnweb";

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

const session = newWebSocketRpcSession<Api>("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
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions