mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
Taking the head entry of a Readable's buffer moved every remaining entry down one slot, so draining a queue of n buffered chunks cost O(n²). The buffer now keeps the index of its first entry: a take advances it, a push at the tail moves the entries down only when at least half the slots are free at the front (and grows otherwise), and unshift takes a freed front slot when there is one. The drop, trace and boxing loops walk the entries from that index. The stream-buffered-drain runtime workload buffers 200,000 objects and 100,000 Buffers before draining them; corpus 8533 covers reads across entries, unshift into a freed slot and onto a part-read head, setEncoding after takes, and object-mode takes, unshifts and pushes.
34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
// A Readable's buffered queue after its head moved: read(n) across
|
|
// entries, unshift into the freed front slot and onto a part-read head,
|
|
// setEncoding after takes, and object-mode takes, unshifts and pushes that
|
|
// reuse the freed slots.
|
|
import { Readable } from "node:stream";
|
|
|
|
const bytes = new Readable({ read() {} });
|
|
for (let i = 0; i < 40; i++) bytes.push(Buffer.from(`c${i};`));
|
|
const out: string[] = [];
|
|
out.push(String(bytes.read(7)));
|
|
out.push(String(bytes.read(4)));
|
|
bytes.unshift(Buffer.from("U1;"));
|
|
out.push(String(bytes.read(5)));
|
|
bytes.unshift(Buffer.from("U2;"));
|
|
out.push(String(bytes.read(30)));
|
|
bytes.setEncoding("utf8");
|
|
out.push(String(bytes.read(9)));
|
|
for (let i = 40; i < 60; i++) bytes.push(Buffer.from(`d${i};`));
|
|
out.push(String(bytes.read(20)));
|
|
out.push(`left ${bytes.readableLength}`);
|
|
console.log(out.join("\n"));
|
|
|
|
const objects = new Readable({ objectMode: true, highWaterMark: 4, read() {} });
|
|
for (let i = 0; i < 12; i++) objects.push({ n: i });
|
|
const seen: number[] = [];
|
|
for (let i = 0; i < 9; i++) seen.push((objects.read() as { n: number }).n);
|
|
objects.unshift({ n: 100 });
|
|
objects.unshift({ n: 101 });
|
|
for (let i = 12; i < 40; i++) objects.push({ n: i });
|
|
let row: { n: number } | null;
|
|
while ((row = objects.read() as { n: number } | null) !== null) seen.push(row.n);
|
|
console.log(seen.join(","));
|
|
console.log(`object left ${objects.readableLength}`);
|