Skip to content

Commit 5e34722

Browse files
perf: add the wsPreEncodedFrame option
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
1 parent 8a937a4 commit 5e34722

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

Diff for: lib/transports/websocket.ts

+20
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,31 @@ export class WebSocket extends Transport {
9393

9494
if (packet.options && typeof packet.options.wsPreEncoded === "string") {
9595
send(packet.options.wsPreEncoded);
96+
} else if (this._canSendPreEncodedFrame(packet)) {
97+
// the WebSocket frame was computed with WebSocket.Sender.frame()
98+
// see https://github.com/websockets/ws/issues/617#issuecomment-283002469
99+
this.socket._sender.sendFrame(packet.options.wsPreEncodedFrame, err => {
100+
if (err) return this.onError("write error", err.stack);
101+
this.send(packets);
102+
});
96103
} else {
97104
this.parser.encodePacket(packet, this.supportsBinary, send);
98105
}
99106
}
100107

108+
/**
109+
* Whether the encoding of the WebSocket frame can be skipped.
110+
* @param packet
111+
* @private
112+
*/
113+
private _canSendPreEncodedFrame(packet) {
114+
return (
115+
!this.perMessageDeflate &&
116+
typeof this.socket?._sender?.sendFrame === "function" &&
117+
packet.options?.wsPreEncodedFrame !== undefined
118+
);
119+
}
120+
101121
/**
102122
* Closes the transport.
103123
*

Diff for: test/server.js

+47
Original file line numberDiff line numberDiff line change
@@ -2822,6 +2822,53 @@ describe("server", () => {
28222822
});
28232823
});
28242824
});
2825+
2826+
it("should use the pre-encoded frame", function(done) {
2827+
if (process.env.EIO_WS_ENGINE === "uws") {
2828+
return this.skip();
2829+
}
2830+
engine = listen(port => {
2831+
client = new ClientSocket(`ws://localhost:${port}`, {
2832+
transports: ["websocket"]
2833+
});
2834+
2835+
engine.on("connection", conn => {
2836+
conn.send("test", {
2837+
wsPreEncodedFrame: [
2838+
Buffer.from([129, 4]),
2839+
Buffer.from([52, 49, 50, 51])
2840+
]
2841+
});
2842+
});
2843+
2844+
client.on("message", msg => {
2845+
expect(msg).to.be("123");
2846+
done();
2847+
});
2848+
});
2849+
});
2850+
2851+
it("should not use the pre-encoded frame when the permessage-deflate extension is enabled", done => {
2852+
engine = listen({ perMessageDeflate: true }, port => {
2853+
client = new ClientSocket(`ws://localhost:${port}`, {
2854+
transports: ["websocket"]
2855+
});
2856+
2857+
engine.on("connection", conn => {
2858+
conn.send("test", {
2859+
wsPreEncodedFrame: [
2860+
Buffer.from([129, 4]),
2861+
Buffer.from([52, 49, 50, 51])
2862+
]
2863+
});
2864+
});
2865+
2866+
client.on("message", msg => {
2867+
expect(msg).to.be("test");
2868+
done();
2869+
});
2870+
});
2871+
});
28252872
});
28262873
});
28272874

0 commit comments

Comments
 (0)