gpt4 book ai didi

javascript - 在多个框架上分配长时间运行的任务的最佳方法是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:39:43 34 4
gpt4 key购买 nike

我有多个长时间运行的任务,比如超过 ~10 毫秒,这会影响浏览器的响应能力。最糟糕的任务,例如从文件加载和解析 3D 模型,已经卸载到 Web Workers,因此它们不会影响渲染循环。

但是,有些任务不容易移植到 Workers,因此必须分布在主线程中的多个框架上。我不想一次完成 1 秒的任务,而是想将其拆分为 ~5ms 的包,让浏览器有机会在两者之间执行其他事件(鼠标移动、requestAnimationFrame 等)。

生成器函数与 setTimeout 相结合,似乎是最简单的方法。我一起破解了一些可以完成这项工作的东西,但我想知道是否有更好/更干净的方法来解决这个问题。

下面的代码计算了 1 亿次 Math.random() 调用的平均值。第一个版本一次计算平均值,但会使浏览器停止约 1.3 秒。第二个版本滥用生成器函数在每 500 万个点后产生,从而使浏览器有机会在其间执行其他事件(鼠标移动)。生成器函数通过 setTimout 循环重复调用,直到处理完所有 1 亿个样本。

<html>
<head></head>
<body>

<script>

let samples = 100 * 1000 * 1000;

{ // run complete task at once, possibly stalling the browser
function run(){
let start = performance.now();

let sum = 0.0;
for(let i = 0; i < samples; i++){
sum = sum + Math.random();
}

let mean = sum / samples;

let duration = performance.now() - start;

console.log(`single-run: duration: ${duration}`);
console.log(`single-run: sum: ${sum}`);
console.log(`single-run: mean: ${mean}`);
}
run();
}


{ // run in smaller packages to keep browser responsive

// move mouse to check if this callback is executed in between
document.body.addEventListener("mousemove", () => {
console.log("mouse moved");
});

function * distributedRun(){
let start = performance.now();

let packageSize = 5 * 1000 * 1000;
let sum = 0.0;
for(let i = 0; i < samples; i++){
sum = sum + Math.random();

if((i % packageSize) === 0){
yield sum;
}
}

let mean = sum / samples;

let duration = performance.now() - start;


console.log(`distributed-run: duration: ${duration}`);
console.log(`distributed-run: sum: ${sum}`);
console.log(`distributed-run: mean: ${mean}`);

yield sum;
}

let generatorInstance = distributedRun();
function loop(){
let result = generatorInstance.next();
console.log(`distributed-run intermediate result: ${result.value}`);

if(!result.done){
setTimeout(loop, 0);
}
}
loop();
}

</script>

</body>
</html>

ES2018 有异步迭代器,这听起来像我正在寻找的东西,但我不确定它们是否真的适用于此类问题。像这样使用它仍然会使浏览器停止运行:

for await (const result of distributedRun()) {
...
}

(在这里和那里以及在 runDistributed() 函数中尝试了一些异步,但老实说,我仍在学习 await/async 的细节)

最佳答案

这是您的代码的一个略微修改版本。如果您根据计算复杂度和允许的延迟量调整 chunk,它应该可以正常工作。

let samples = 100 * 1000 * 1000;
let chunk = 100000;

async function run() {
let sum = 0.0;
for(let i=0; i<samples; i++) {
sum += Math.random();

if (i % chunk === 0) {
console.log("finished chunk")
// wait for the next tick
await new Promise(res => setTimeout(res, 0));
}
}

let mean = sum / samples;
console.log("finished computation", mean);
}

setTimeout(run, 0);

关于javascript - 在多个框架上分配长时间运行的任务的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48642171/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com