Skip to content

Commit 7b0e7a2

Browse files
committed
stream: avoid allocations on every stream/iter push() write
Every write() to a push() or broadcast() writer converted its options with the WriteOptions dictionary converter to look for a signal, which creates an empty dictionary when there are no options, and every write replaced the array of pending drains, even when there were none. Return no signal for undefined or null options without converting them, and leave the array of pending drains alone when it is empty. Writing 16-byte chunks to a push() stream with await write() and reading them is about 30% faster, and about 18% faster when piping them; 64 KiB chunks are about 11% faster. Assisted-by: OpenCode Signed-off-by: James M Snell <jasnell@gmail.com>
1 parent dea0e3e commit 7b0e7a2

3 files changed

Lines changed: 7 additions & 0 deletions

File tree

‎lib/internal/streams/iter/broadcast.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ class BroadcastWriter {
839839
}
840840

841841
#resolvePendingDrains(canWrite) {
842+
if (this.#pendingDrains.length === 0) return;
842843
const drains = this.#pendingDrains;
843844
this.#pendingDrains = [];
844845
for (let i = 0; i < drains.length; i++) {
@@ -847,6 +848,7 @@ class BroadcastWriter {
847848
}
848849

849850
#rejectPendingDrains(error) {
851+
if (this.#pendingDrains.length === 0) return;
850852
const drains = this.#pendingDrains;
851853
this.#pendingDrains = [];
852854
for (let i = 0; i < drains.length; i++) {

‎lib/internal/streams/iter/push.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ class PushQueue {
594594
}
595595

596596
#resolvePendingDrains(canWrite) {
597+
if (this.#pendingDrains.length === 0) return;
597598
const drains = this.#pendingDrains;
598599
this.#pendingDrains = [];
599600
for (let i = 0; i < drains.length; i++) {
@@ -602,6 +603,7 @@ class PushQueue {
602603
}
603604

604605
#rejectPendingDrains(error) {
606+
if (this.#pendingDrains.length === 0) return;
605607
const drains = this.#pendingDrains;
606608
this.#pendingDrains = [];
607609
for (let i = 0; i < drains.length; i++) {

‎lib/internal/streams/iter/utils.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,9 @@ function convertChunks(chunks) {
707707
* @returns {AbortSignal|undefined}
708708
*/
709709
function getWriterSignal(options) {
710+
// Writes are hot, and converting undefined or null creates an empty
711+
// dictionary, which has no signal.
712+
if (options === undefined || options === null) return undefined;
710713
return converters.WriteOptions(options, kWriteOptionsContext).signal;
711714
}
712715

0 commit comments

Comments
 (0)