perf: harden realtime localization pipeline
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
let messageChannelYield;
|
||||
let cooperativeTurn = 0;
|
||||
|
||||
export const COOPERATIVE_TIMER_TURN_INTERVAL = 8;
|
||||
|
||||
function createMessageChannelYield() {
|
||||
if (typeof globalThis.MessageChannel !== "function") return undefined;
|
||||
const channel = new globalThis.MessageChannel();
|
||||
const queue = [];
|
||||
channel.port1.onmessage = () => queue.shift()?.();
|
||||
channel.port1.unref?.();
|
||||
channel.port2.unref?.();
|
||||
return () => new Promise((resolve) => {
|
||||
queue.push(resolve);
|
||||
channel.port2.postMessage(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Yield one cooperative task without relying on nested zero-delay timers.
|
||||
* scheduler.yield() is preferred when the host implements it; MessageChannel
|
||||
* keeps the fallback task-based and avoids browser timer clamping.
|
||||
*/
|
||||
export function cooperativeYield() {
|
||||
cooperativeTurn += 1;
|
||||
if (cooperativeTurn % COOPERATIVE_TIMER_TURN_INTERVAL === 0) {
|
||||
return new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
const hostScheduler = globalThis.scheduler;
|
||||
if (typeof hostScheduler?.yield === "function") {
|
||||
try {
|
||||
return hostScheduler.yield();
|
||||
} catch {
|
||||
// A partial scheduler implementation must not make computation unusable.
|
||||
}
|
||||
}
|
||||
messageChannelYield ??= createMessageChannelYield();
|
||||
if (messageChannelYield) return messageChannelYield();
|
||||
return new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
Reference in New Issue
Block a user