0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Batch iterator buffering to reduce number of timeout calls (#7544)

This commit is contained in:
Johannes Spohr 2023-07-04 11:32:01 +02:00 committed by GitHub
parent 7419bb6cf2
commit 47b756e3e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Batch async iterator buffering to reduce numbers of calls to `setTimeout`

View file

@ -146,6 +146,26 @@ export function renderElement(
return `<${name}${internalSpreadAttributes(props, shouldEscape)}>${children}</${name}>`;
}
const iteratorQueue: EagerAsyncIterableIterator[][] = [];
/**
* Takes an array of iterators and adds them to a list of iterators to start buffering
* as soon as the execution flow is suspended for the first time. We expect a lot
* of calls to this function before the first suspension, so to reduce the number
* of calls to setTimeout we batch the buffering calls.
* @param iterators
*/
function queueIteratorBuffers(iterators: EagerAsyncIterableIterator[]) {
if (iteratorQueue.length === 0) {
setTimeout(() => {
// buffer all iterators that haven't started yet
iteratorQueue.forEach((its) => its.forEach((it) => !it.isStarted() && it.buffer()));
iteratorQueue.length = 0; // fastest way to empty an array
});
}
iteratorQueue.push(iterators);
}
/**
* This will take an array of async iterables and start buffering them eagerly.
* To avoid useless buffering, it will only start buffering the next tick, so the
@ -156,10 +176,7 @@ export function bufferIterators<T>(iterators: AsyncIterable<T>[]): AsyncIterable
const eagerIterators = iterators.map((it) => new EagerAsyncIterableIterator(it));
// once the execution of the next for loop is suspended due to an async component,
// this timeout triggers and we start buffering the other iterators
queueMicrotask(() => {
// buffer all iterators that haven't started yet
eagerIterators.forEach((it) => !it.isStarted() && it.buffer());
});
queueIteratorBuffers(eagerIterators);
return eagerIterators;
}