mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
307af044bc
* perf(artifacts): overlap bundle magic reads while enumerating dylib roots trace_dylib_resolution opened every file of an app bundle one at a time to read its Mach-O magic (Keynote: 35,971 files, 23 Mach-O images). Keep up to eight reads in flight while the directory walk continues, settling them in walk order so classification and failure precedence match the sequential scan. Keynote 4.20 s -> 2.78 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(artifacts): pin ordered-read failure precedence and cleanup Extract the overlapped magic-read queue into consumeWithOrderedReads and test its ordering, concurrency bound, failure precedence, enumeration close and read settlement with controlled promises. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
type Settled<Value> =
|
|
| { readonly ok: true; readonly value: Value }
|
|
| { readonly ok: false; readonly error: unknown };
|
|
|
|
/**
|
|
* Overlap independent reads with an enumeration while consuming their results
|
|
* in enumeration order. `read` returns undefined for items it skips. At most
|
|
* `width` reads are in flight. A failure is reported as a one-at-a-time loop
|
|
* would report it: an earlier item's read or consume failure wins over a
|
|
* later read failure or an enumeration failure. Every started read settles
|
|
* before this returns or throws, and an enumeration left early is closed as
|
|
* `for await` would close it.
|
|
*/
|
|
export const consumeWithOrderedReads = async <Item, Value>(
|
|
items: AsyncIterable<Item>,
|
|
width: number,
|
|
read: (item: Item) => Promise<Value> | undefined,
|
|
consume: (item: Item, value: Value) => Promise<void>,
|
|
): Promise<void> => {
|
|
const pending: {
|
|
readonly item: Item;
|
|
readonly result: Promise<Settled<Value>>;
|
|
}[] = [];
|
|
const consumeNext = async (): Promise<void> => {
|
|
const next = pending.shift();
|
|
if (next === undefined) return;
|
|
const result = await next.result;
|
|
if (!result.ok) throw result.error;
|
|
await consume(next.item, result.value);
|
|
};
|
|
const iterator = items[Symbol.asyncIterator]();
|
|
let iterating = true;
|
|
try {
|
|
while (iterating) {
|
|
let step: IteratorResult<Item>;
|
|
try {
|
|
step = await iterator.next();
|
|
} catch (cause: unknown) {
|
|
iterating = false;
|
|
while (pending.length > 0) await consumeNext();
|
|
throw cause;
|
|
}
|
|
if (step.done === true) {
|
|
iterating = false;
|
|
break;
|
|
}
|
|
const started = read(step.value);
|
|
if (started === undefined) continue;
|
|
pending.push({
|
|
item: step.value,
|
|
result: started.then(
|
|
(value) => ({ ok: true, value }) as const,
|
|
(error: unknown) => ({ ok: false, error }) as const,
|
|
),
|
|
});
|
|
if (pending.length >= width) await consumeNext();
|
|
}
|
|
while (pending.length > 0) await consumeNext();
|
|
} finally {
|
|
if (iterating) await iterator.return?.().catch(() => undefined);
|
|
await Promise.all(pending.map(({ result }) => result));
|
|
}
|
|
};
|