Skip to content

Commit

Permalink
perf: add the wsPreEncodedFrame option
Browse files Browse the repository at this point in the history
This optimization is only applied if:

- the permessage-deflate extension is disabled (which is the default)
- the "ws" package is used (which is the default)

In that case, the WebSocket frame will only be computed once, when
broadcasting to multiple clients.

Related: socketio/socket.io-adapter@5f7b47d
  • Loading branch information
darrachequesne committed Jan 9, 2023
1 parent 8a937a4 commit 5e34722
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/transports/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,31 @@ export class WebSocket extends Transport {

if (packet.options && typeof packet.options.wsPreEncoded === "string") {
send(packet.options.wsPreEncoded);
} else if (this._canSendPreEncodedFrame(packet)) {
// the WebSocket frame was computed with WebSocket.Sender.frame()
// see https://github.com/websockets/ws/issues/617#issuecomment-283002469
this.socket._sender.sendFrame(packet.options.wsPreEncodedFrame, err => {
if (err) return this.onError("write error", err.stack);
this.send(packets);
});
} else {
this.parser.encodePacket(packet, this.supportsBinary, send);
}
}

/**
* Whether the encoding of the WebSocket frame can be skipped.
* @param packet
* @private
*/
private _canSendPreEncodedFrame(packet) {
return (
!this.perMessageDeflate &&
typeof this.socket?._sender?.sendFrame === "function" &&
packet.options?.wsPreEncodedFrame !== undefined
);
}

/**
* Closes the transport.
*
Expand Down
47 changes: 47 additions & 0 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2822,6 +2822,53 @@ describe("server", () => {
});
});
});

it("should use the pre-encoded frame", function(done) {
if (process.env.EIO_WS_ENGINE === "uws") {
return this.skip();
}
engine = listen(port => {
client = new ClientSocket(`ws://localhost:${port}`, {
transports: ["websocket"]
});

engine.on("connection", conn => {
conn.send("test", {
wsPreEncodedFrame: [
Buffer.from([129, 4]),
Buffer.from([52, 49, 50, 51])
]
});
});

client.on("message", msg => {
expect(msg).to.be("123");
done();
});
});
});

it("should not use the pre-encoded frame when the permessage-deflate extension is enabled", done => {
engine = listen({ perMessageDeflate: true }, port => {
client = new ClientSocket(`ws://localhost:${port}`, {
transports: ["websocket"]
});

engine.on("connection", conn => {
conn.send("test", {
wsPreEncodedFrame: [
Buffer.from([129, 4]),
Buffer.from([52, 49, 50, 51])
]
});
});

client.on("message", msg => {
expect(msg).to.be("test");
done();
});
});
});
});
});

Expand Down

0 comments on commit 5e34722

Please sign in to comment.