Why is this so slow?
Chrome (Blink) actually sets the minimum timeout to 4 ms:
// Chromium uses a minimum timer interval of 4ms. We'd like to go
// lower; however, there are poorly coded websites out there which do
// create CPU-spinning loops. Using 4ms prevents the CPU from
// spinning too busily and provides a balance between CPU spinning and
// the smallest possible interval timer.
static constexpr base::TimeDelta kMinimumInterval =
base::TimeDelta::FromMilliseconds(4);
Edit: If you read further in the code, that minimum is only used if the nesting level is more than 5, however it does still set the minimum to 1 ms in all cases:
base::TimeDelta interval_milliseconds =
std::max(base::TimeDelta::FromMilliseconds(1), interval);
if (interval_milliseconds < kMinimumInterval &&
nesting_level_ >= kMaxTimerNestingLevel)
interval_milliseconds = kMinimumInterval;
Apparently the WHATWG and W3C specs disagree about whether the minimum of 4 ms should always apply or only apply above a certain nesting level, but the WHATWG spec is the one that matters for HTML and it seems like Chrome has implemented that.
I'm not sure why my measurements indicate it still takes 4 ms though.
is there a faster way to do this?
Based on Kaiido's great idea to use another message channel you can do something like this:
let currentTask = {
cancelled: false,
}
onmessage = event => {
currentTask.cancelled = true;
currentTask = {
cancelled: false,
};
performComputation(currentTask, event.data);
}
async function performComputation(task, data) {
let total = 0;
let promiseResolver;
const channel = new MessageChannel();
channel.port2.onmessage = event => {
promiseResolver();
};
while (data !== 0) {
// Do a little bit of computation.
total += data;
--data;
// Yield to the event loop.
const promise = new Promise(resolve => {
promiseResolver = resolve;
});
channel.port1.postMessage(null);
await promise;
// Check if this task has been superceded by another one.
if (task.cancelled) {
return;
}
}
// Return the result.
postMessage(total);
}
I'm not totally happy with this code, but it does seem to work and is waaay faster. Each loop takes around 0.04 ms on my machine.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…