summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorMarcos Casagrande <marcos@denode.com>2023-10-06 23:21:48 +0200
committerGitHub <noreply@github.com>2023-10-06 23:21:48 +0200
commitceecd8c495619284eee5763c1adb4afba345dceb (patch)
tree098e8cb76c5df08dd006bcda62343d0a02d6a199 /ext
parentcba5ae45c2422a4cf9df3a149a646a191a8f27b2 (diff)
perf(ext/web): optimize structuredClone without transferables (#20730)
This PR optimizes `structuredClone` when it's called without transferables. ### Benchmarks **main** ``` cpu: 13th Gen Intel(R) Core(TM) i9-13900H runtime: deno 1.37.1 (x86_64-unknown-linux-gnu) benchmark time (avg) iter/s (min … max) p75 p99 p995 ----------------------------------------------------------------------------------- ----------------------------- structuredClone object 1.64 µs/iter 611,086.0 (1.58 µs … 1.84 µs) 1.66 µs 1.84 µs 1.84 µs structuredClone transferables 2.82 µs/iter 354,281.4 (2.78 µs … 2.92 µs) 2.84 µs 2.92 µs 2.92 µs ``` **this PR** ``` cpu: 13th Gen Intel(R) Core(TM) i9-13900H runtime: deno 1.37.1 (x86_64-unknown-linux-gnu) structuredClone object 1 µs/iter 998,383.5 (971.28 ns … 1.2 µs) 1 µs 1.2 µs 1.2 µs structuredClone transferables 2.82 µs/iter 355,087.5 (2.7 µs … 3.07 µs) 2.83 µs 3.07 µs 3.07 µs ``` ```js Deno.bench("structuredClone object", () => { structuredClone({ foo: "bar" }); }); Deno.bench("structuredClone transferables", () => { const buf = new Uint8Array([97]); structuredClone(buf, { transfer: [buf.buffer], }); }); ```
Diffstat (limited to 'ext')
-rw-r--r--ext/web/13_message_port.js92
1 files changed, 51 insertions, 41 deletions
diff --git a/ext/web/13_message_port.js b/ext/web/13_message_port.js
index 40145db78..ffbc48812 100644
--- a/ext/web/13_message_port.js
+++ b/ext/web/13_message_port.js
@@ -205,34 +205,39 @@ function opCreateEntangledMessagePort() {
function deserializeJsMessageData(messageData) {
/** @type {object[]} */
const transferables = [];
- const hostObjects = [];
const arrayBufferIdsInTransferables = [];
const transferredArrayBuffers = [];
+ let options;
- for (let i = 0; i < messageData.transferables.length; ++i) {
- const transferable = messageData.transferables[i];
- switch (transferable.kind) {
- case "messagePort": {
- const port = createMessagePort(transferable.data);
- ArrayPrototypePush(transferables, port);
- ArrayPrototypePush(hostObjects, port);
- break;
- }
- case "arrayBuffer": {
- ArrayPrototypePush(transferredArrayBuffers, transferable.data);
- const index = ArrayPrototypePush(transferables, null);
- ArrayPrototypePush(arrayBufferIdsInTransferables, index);
- break;
+ if (messageData.transferables.length > 0) {
+ const hostObjects = [];
+ for (let i = 0; i < messageData.transferables.length; ++i) {
+ const transferable = messageData.transferables[i];
+ switch (transferable.kind) {
+ case "messagePort": {
+ const port = createMessagePort(transferable.data);
+ ArrayPrototypePush(transferables, port);
+ ArrayPrototypePush(hostObjects, port);
+ break;
+ }
+ case "arrayBuffer": {
+ ArrayPrototypePush(transferredArrayBuffers, transferable.data);
+ const index = ArrayPrototypePush(transferables, null);
+ ArrayPrototypePush(arrayBufferIdsInTransferables, index);
+ break;
+ }
+ default:
+ throw new TypeError("Unreachable");
}
- default:
- throw new TypeError("Unreachable");
}
+
+ options = {
+ hostObjects,
+ transferredArrayBuffers,
+ };
}
- const data = core.deserialize(messageData.data, {
- hostObjects,
- transferredArrayBuffers,
- });
+ const data = core.deserialize(messageData.data, options);
for (let i = 0; i < arrayBufferIdsInTransferables.length; ++i) {
const id = arrayBufferIdsInTransferables[i];
@@ -248,31 +253,36 @@ function deserializeJsMessageData(messageData) {
* @returns {messagePort.MessageData}
*/
function serializeJsMessageData(data, transferables) {
+ let options;
const transferredArrayBuffers = [];
- for (let i = 0, j = 0; i < transferables.length; i++) {
- const ab = transferables[i];
- if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
- if (
- ArrayBufferPrototypeGetByteLength(ab) === 0 &&
- ops.op_arraybuffer_was_detached(ab)
- ) {
- throw new DOMException(
- `ArrayBuffer at index ${j} is already detached`,
- "DataCloneError",
- );
+ if (transferables.length > 0) {
+ const hostObjects = [];
+ for (let i = 0, j = 0; i < transferables.length; i++) {
+ const t = transferables[i];
+ if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, t)) {
+ if (
+ ArrayBufferPrototypeGetByteLength(t) === 0 &&
+ ops.op_arraybuffer_was_detached(t)
+ ) {
+ throw new DOMException(
+ `ArrayBuffer at index ${j} is already detached`,
+ "DataCloneError",
+ );
+ }
+ j++;
+ ArrayPrototypePush(transferredArrayBuffers, t);
+ } else if (ObjectPrototypeIsPrototypeOf(MessagePortPrototype, t)) {
+ ArrayPrototypePush(hostObjects, t);
}
- j++;
- ArrayPrototypePush(transferredArrayBuffers, ab);
}
+
+ options = {
+ hostObjects,
+ transferredArrayBuffers,
+ };
}
- const serializedData = core.serialize(data, {
- hostObjects: ArrayPrototypeFilter(
- transferables,
- (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a),
- ),
- transferredArrayBuffers,
- }, (err) => {
+ const serializedData = core.serialize(data, options, (err) => {
throw new DOMException(err, "DataCloneError");
});