diff options
author | Matt Mastracci <matthew@mastracci.com> | 2023-06-06 07:58:18 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-06 07:58:18 -0600 |
commit | df76a062fa93899a614194a34f7b7c281f9dbac5 (patch) | |
tree | 4de33bf780c637b4bf201dbdf111f6f67d3b94f2 /ext/websocket/01_websocket.js | |
parent | 42991017e9af59d6a5cb6b523228c62f1c32380e (diff) |
perf(ext/websocket): Make send sync for non-stream websockets (#19376)
No need to go through the async machinery for `send(String | Buffer)` --
we can fire and forget, and then route any send errors into the async
call we're already making (`op_ws_next_event`).
Early benchmark on MacOS:
Before: 155.8k msg/sec
After: 166.2k msg/sec (+6.6%)
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/websocket/01_websocket.js')
-rw-r--r-- | ext/websocket/01_websocket.js | 56 |
1 files changed, 13 insertions, 43 deletions
diff --git a/ext/websocket/01_websocket.js b/ext/websocket/01_websocket.js index 01dd26579..a38af036a 100644 --- a/ext/websocket/01_websocket.js +++ b/ext/websocket/01_websocket.js @@ -23,12 +23,10 @@ const primordials = globalThis.__bootstrap.primordials; const { ArrayBufferPrototype, ArrayBufferIsView, - ArrayBufferPrototypeGetByteLength, ArrayPrototypeJoin, ArrayPrototypeMap, ArrayPrototypeSome, DataView, - DataViewPrototypeGetByteLength, ErrorPrototypeToString, ObjectDefineProperties, ObjectPrototypeIsPrototypeOf, @@ -46,7 +44,6 @@ const { PromisePrototypeCatch, SymbolFor, TypedArrayPrototypeGetByteLength, - TypedArrayPrototypeGetSymbolToStringTag, } = primordials; const op_ws_check_permission_and_cancel_handle = core.ops.op_ws_check_permission_and_cancel_handle; @@ -57,6 +54,7 @@ const { op_ws_send_text, op_ws_next_event, op_ws_send_ping, + op_ws_get_buffered_amount, } = core.ensureFastOps(); webidl.converters["sequence<DOMString> or DOMString"] = ( @@ -111,7 +109,6 @@ const _role = Symbol("[[role]]"); const _extensions = Symbol("[[extensions]]"); const _protocol = Symbol("[[protocol]]"); const _binaryType = Symbol("[[binaryType]]"); -const _bufferedAmount = Symbol("[[bufferedAmount]]"); const _eventLoop = Symbol("[[eventLoop]]"); const _server = Symbol("[[server]]"); @@ -179,10 +176,13 @@ class WebSocket extends EventTarget { } } - [_bufferedAmount] = 0; get bufferedAmount() { webidl.assertBranded(this, WebSocketPrototype); - return this[_bufferedAmount]; + if (this[_readyState] === OPEN) { + return op_ws_get_buffered_amount(this[_rid]); + } else { + return 0; + } } constructor(url, protocols = []) { @@ -318,55 +318,25 @@ class WebSocket extends EventTarget { throw new DOMException("readyState not OPEN", "InvalidStateError"); } - /** - * @param {ArrayBufferView} view - * @param {number} byteLength - */ - const sendTypedArray = (view, byteLength) => { - this[_bufferedAmount] += byteLength; - PromisePrototypeThen( - op_ws_send_binary( - this[_rid], - view, - ), - () => { - this[_bufferedAmount] -= byteLength; - }, - ); - }; - if (ObjectPrototypeIsPrototypeOf(BlobPrototype, data)) { PromisePrototypeThen( // deno-lint-ignore prefer-primordials data.slice().arrayBuffer(), (ab) => - sendTypedArray( + op_ws_send_binary( + this[_rid], new DataView(ab), - ArrayBufferPrototypeGetByteLength(ab), ), ); } else if (ArrayBufferIsView(data)) { - if (TypedArrayPrototypeGetSymbolToStringTag(data) === undefined) { - // DataView - sendTypedArray(data, DataViewPrototypeGetByteLength(data)); - } else { - // TypedArray - sendTypedArray(data, TypedArrayPrototypeGetByteLength(data)); - } + op_ws_send_binary(this[_rid], data); } else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, data)) { - sendTypedArray(data, ArrayBufferPrototypeGetByteLength(data)); + op_ws_send_binary(this[_rid], data); } else { const string = String(data); - const d = core.encode(string); - this[_bufferedAmount] += TypedArrayPrototypeGetByteLength(d); - PromisePrototypeThen( - op_ws_send_text( - this[_rid], - string, - ), - () => { - this[_bufferedAmount] -= TypedArrayPrototypeGetByteLength(d); - }, + op_ws_send_text( + this[_rid], + string, ); } } |