-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Emit at most one event per event loop iteration #2218
Conversation
I'm not sure why, but with a simple echo benchmark it seems to improve performance in all cases, especially on Linux
cc: @OrKoN |
This is more in line with the expectations
The echo benchmark is a special case. |
// server.js
const { createHash } = require('crypto');
const { createServer } = require('http');
const { Readable } = require('stream');
const { Sender } = require('ws');
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const buf = Buffer.alloc(125);
const frame = Buffer.concat(Sender.frame(buf, { fin: true, opcode: 2 }));
const readable = new Readable({
read() {
this.push(frame);
}
});
const server = createServer();
server.on('upgrade', function (request, socket) {
const key = createHash('sha1')
.update(request.headers['sec-websocket-key'] + GUID)
.digest('base64');
socket.write(
[
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
`Sec-WebSocket-Accept: ${key}`,
'\r\n'
].join('\r\n')
);
readable.pipe(socket);
});
server.listen(8080, function () {
console.log('Server listening on [::]:8080');
}); // client.js
const prettierBytes = require('prettier-bytes');
const speedometer = require('speedometer');
const WebSocket = require('ws');
const speed = speedometer();
const ws = new WebSocket('ws://localhost:8080');
ws.on('message', function (data) {
speed(data.length);
});
setInterval(function () {
console.log(prettierBytes(speed()) + '/s');
}, 2000);
|
On my macbook pro m1 I see different results:
|
Yes, I also saw similar results on macOS yesterday. I can't make this the new default if the same happens also on Linux. The results in #2218 (comment) are coming from WSL 2. Below are the results on Windows.
|
Below are the results on Linux on bare metal
|
I have also tried the following client benchmark:
Edit: corrected result labels |
We are not able to replicate the regression on a Linux bare metal machine. I think the benchmark is a bit flawed since it exercises the network stack and it is probably affected by the OS scheduler, network stack etc. For example, in the browser the network messages probably go throw the network service resulting in some IPC roundtrips. I guess to measure the impact correctly we would need to mock the network stack and dispatch client events in some other way. Also, I think I mentioned this but this sort of logic for event dispatch is only-speced for the client and the server side does not need it as there is no need for interoperability. |
It should exercises the network stack, otherwise a reliable benchmark is this one #2218 (comment) 🥲
Yes, but there is only one |
What do you think about flipping the default value of the I don't like to restore the original non WHATWG compliant behavior but I see no other way. In hindsight following the spec here was a mistake. |
Many small messages (30 bytes) in the same data chunk // server.js
const { createHash } = require('crypto');
const { createServer } = require('http');
const { Readable } = require('stream');
const { Sender } = require('ws');
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const buf = Buffer.alloc(30);
const frame = Buffer.concat(Sender.frame(buf, { fin: true, opcode: 2 }));
const data = Buffer.concat(new Array(512).fill(frame));
const readable = new Readable({
read() {
this.push(data);
}
});
const server = createServer();
server.on('upgrade', function (request, socket) {
const key = createHash('sha1')
.update(request.headers['sec-websocket-key'] + GUID)
.digest('base64');
socket.write(
[
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
`Sec-WebSocket-Accept: ${key}`,
'\r\n'
].join('\r\n')
);
readable.pipe(socket);
});
server.listen(8080, function () {
console.log('Server listening on [::]:8080');
}); // client.js
const WebSocket = require('ws');
let messages = 0;
const ws = new WebSocket('ws://127.0.0.1:8080');
ws.on('open', function () {
console.time('ws');
});
ws.on('message', function () {
if (++messages === 10_000_000) {
console.timeEnd('ws');
ws.terminate();
}
});
|
Flip the default value of the `allowSynchronousEvents` option to `true`. Refs: #2218
Flip the default value of the `allowSynchronousEvents` option to `true`. Refs: #2218
@OrKoN any feedback/suggestions? Is it inconvenient for you to use the |
@lpinca sorry, for the delay, requiring an option to opt-in into more spec-aligned behaviour would work for us, thanks! |
Flip the default value of the `allowSynchronousEvents` option to `true`. Refs: #2218
Flip the default value of the `allowSynchronousEvents` option to `true`. Refs: #2218
Flip the default value of the `allowSynchronousEvents` option to `true`. Refs: #2218
Fixes #2216