From e4870d84be19f4ea768933522eff437f64963730 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Fri, 7 Jul 2023 22:17:08 +0530 Subject: perf(ext/node): native vectored write for server streams (#19752) ``` # main $ ./load_test 10 0.0.0.0 8080 0 0 Using message size of 20 bytes Running benchmark now... Msg/sec: 106182.250000 Msg/sec: 110279.750000 ^C # this PR $ ./load_test 10 0.0.0.0 8080 0 0 Using message size of 20 bytes Running benchmark now... Msg/sec: 131632.250000 Msg/sec: 134754.250000 ^C ``` --- ext/node/polyfills/internal_binding/stream_wrap.ts | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'ext/node/polyfills/internal_binding') diff --git a/ext/node/polyfills/internal_binding/stream_wrap.ts b/ext/node/polyfills/internal_binding/stream_wrap.ts index 27870b20b..95f60fe95 100644 --- a/ext/node/polyfills/internal_binding/stream_wrap.ts +++ b/ext/node/polyfills/internal_binding/stream_wrap.ts @@ -40,6 +40,9 @@ import { } from "ext:deno_node/internal_binding/async_wrap.ts"; import { codeMap } from "ext:deno_node/internal_binding/uv.ts"; +const core = globalThis.Deno.core; +const { ops } = core; + interface Reader { read(p: Uint8Array): Promise; } @@ -54,7 +57,7 @@ export interface Closer { type Ref = { ref(): void; unref(): void }; -enum StreamBaseStateFields { +const enum StreamBaseStateFields { kReadBytesOrError, kArrayBufferOffset, kBytesWritten, @@ -195,6 +198,31 @@ export class LibuvStreamWrap extends HandleWrap { chunks: Buffer[] | (string | Buffer)[], allBuffers: boolean, ): number { + const supportsWritev = this.provider === providerType.TCPSERVERWRAP; + // Fast case optimization: two chunks, and all buffers. + if (chunks.length === 2 && allBuffers && supportsWritev) { + // String chunks. + if (typeof chunks[0] === "string") chunks[0] = Buffer.from(chunks[0]); + if (typeof chunks[1] === "string") chunks[1] = Buffer.from(chunks[1]); + + ops.op_raw_write_vectored( + this[kStreamBaseField]!.rid, + chunks[0], + chunks[1], + ).then((nwritten) => { + try { + req.oncomplete(0); + } catch { + // swallow callback errors. + } + + streamBaseState[kBytesWritten] = nwritten; + this.bytesWritten += nwritten; + }); + + return 0; + } + const count = allBuffers ? chunks.length : chunks.length >> 1; const buffers: Buffer[] = new Array(count); -- cgit v1.2.3