mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
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], }); }); ```
This commit is contained in:
parent
cba5ae45c2
commit
ceecd8c495
1 changed files with 51 additions and 41 deletions
|
@ -205,34 +205,39 @@ function opCreateEntangledMessagePort() {
|
||||||
function deserializeJsMessageData(messageData) {
|
function deserializeJsMessageData(messageData) {
|
||||||
/** @type {object[]} */
|
/** @type {object[]} */
|
||||||
const transferables = [];
|
const transferables = [];
|
||||||
const hostObjects = [];
|
|
||||||
const arrayBufferIdsInTransferables = [];
|
const arrayBufferIdsInTransferables = [];
|
||||||
const transferredArrayBuffers = [];
|
const transferredArrayBuffers = [];
|
||||||
|
let options;
|
||||||
|
|
||||||
for (let i = 0; i < messageData.transferables.length; ++i) {
|
if (messageData.transferables.length > 0) {
|
||||||
const transferable = messageData.transferables[i];
|
const hostObjects = [];
|
||||||
switch (transferable.kind) {
|
for (let i = 0; i < messageData.transferables.length; ++i) {
|
||||||
case "messagePort": {
|
const transferable = messageData.transferables[i];
|
||||||
const port = createMessagePort(transferable.data);
|
switch (transferable.kind) {
|
||||||
ArrayPrototypePush(transferables, port);
|
case "messagePort": {
|
||||||
ArrayPrototypePush(hostObjects, port);
|
const port = createMessagePort(transferable.data);
|
||||||
break;
|
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");
|
||||||
}
|
}
|
||||||
case "arrayBuffer": {
|
|
||||||
ArrayPrototypePush(transferredArrayBuffers, transferable.data);
|
|
||||||
const index = ArrayPrototypePush(transferables, null);
|
|
||||||
ArrayPrototypePush(arrayBufferIdsInTransferables, index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new TypeError("Unreachable");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options = {
|
||||||
|
hostObjects,
|
||||||
|
transferredArrayBuffers,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = core.deserialize(messageData.data, {
|
const data = core.deserialize(messageData.data, options);
|
||||||
hostObjects,
|
|
||||||
transferredArrayBuffers,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < arrayBufferIdsInTransferables.length; ++i) {
|
for (let i = 0; i < arrayBufferIdsInTransferables.length; ++i) {
|
||||||
const id = arrayBufferIdsInTransferables[i];
|
const id = arrayBufferIdsInTransferables[i];
|
||||||
|
@ -248,31 +253,36 @@ function deserializeJsMessageData(messageData) {
|
||||||
* @returns {messagePort.MessageData}
|
* @returns {messagePort.MessageData}
|
||||||
*/
|
*/
|
||||||
function serializeJsMessageData(data, transferables) {
|
function serializeJsMessageData(data, transferables) {
|
||||||
|
let options;
|
||||||
const transferredArrayBuffers = [];
|
const transferredArrayBuffers = [];
|
||||||
for (let i = 0, j = 0; i < transferables.length; i++) {
|
if (transferables.length > 0) {
|
||||||
const ab = transferables[i];
|
const hostObjects = [];
|
||||||
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
|
for (let i = 0, j = 0; i < transferables.length; i++) {
|
||||||
if (
|
const t = transferables[i];
|
||||||
ArrayBufferPrototypeGetByteLength(ab) === 0 &&
|
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, t)) {
|
||||||
ops.op_arraybuffer_was_detached(ab)
|
if (
|
||||||
) {
|
ArrayBufferPrototypeGetByteLength(t) === 0 &&
|
||||||
throw new DOMException(
|
ops.op_arraybuffer_was_detached(t)
|
||||||
`ArrayBuffer at index ${j} is already detached`,
|
) {
|
||||||
"DataCloneError",
|
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, {
|
const serializedData = core.serialize(data, options, (err) => {
|
||||||
hostObjects: ArrayPrototypeFilter(
|
|
||||||
transferables,
|
|
||||||
(a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a),
|
|
||||||
),
|
|
||||||
transferredArrayBuffers,
|
|
||||||
}, (err) => {
|
|
||||||
throw new DOMException(err, "DataCloneError");
|
throw new DOMException(err, "DataCloneError");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue