将长时间运行的任务分配到多个帧上的最佳方法是什么?

2023-12-22

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

然而,有些任务不容易移植到 Workers,因此必须分布在主线程中的多个框架上。我不想一次性完成 1 秒的任务,而是将其分成约 5 毫秒的包,以便浏览器有机会在其间执行其他事件(鼠标移动、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() 函数中尝试了一些异步,但说实话,我仍在学习等待/异步的细节)


这是您的代码的稍作修改的版本。如果你调整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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将长时间运行的任务分配到多个帧上的最佳方法是什么? 的相关文章

  • 如何测试 javascript 闭包内的函数

    这似乎是不可能的 也可能是 但我正在尝试更多的 TDD 但我总是在闭包方面碰壁 假设我有以下内容 function createSomething init function privateMethod param return init
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 为什么 JavaScript base-36 转换看起来不明确

    我目前正在编写一段使用 Base 36 编码的 JavaScript 我遇到了这个问题 parseInt welcomeback 36 toString 36 看来要回归了 welcomebacg 我在 Chrome 开发者控制台和 Nod
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • 使用 useReducers 调度函数发送多个操作?

    使用时是否可以通过调度函数发送多个动作useReducer挂钩反应 我尝试向它传递一组操作 但这会引发未处理的运行时异常 明确地说 通常会有一个初始状态对象和一个减速器 如下所示 const initialState message1 nu
  • 我想检查 $('#td1').text() === "x" 是否?

    我想检查innerHtml是否有X或O 所以我不能再次添加任何其他东西 但它不起作用 添加检查代码后它就停止了 我在这里尝试做一个简单的XO游戏来更熟悉javascript和jquery 我也不确定是否可以用 jQuery 做到这一点
  • Meteor:应用程序无法在 0.9.1.1 版本上运行

    出现类似错误 Error TypeError undefined is not a function evaluating Template create anonymous function iron dynamic template j
  • 如何监听 jQuery AJAX 请求?

    以下两种实现 ajaxRequest 1 2 的方法应该是等效的 话说回来 为什么验证回调已执行的单元测试 3 在 1 中成功而在 2 中失败 我应该如何重写测试 3 来监视 2 中的成功回调 如果我尝试stub jQuery ajax使用
  • Javascript正则表达式用于字母字符和空格? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我需要一个
  • 从未用 @flow 标记的导入文件中获取类型定义

    TL DR我怎么告诉flow从未声明的导入模块导入类型定义 flow 加长版 流接缝能够从不使用流语法的文件中派生类型 请参阅示例 示例文件 flow js if Math random lt 0 5 var y hello else va
  • 如何将 Google Charts 与 Vue.js 库一起使用?

    我正在尝试使用 Vue js 库使用 Google Charts 制作图表 但我不知道如何添加到 div 这是我尝试做的 这是如何使用普通 javascript 添加图表 这是文档的代码示例 https developers google
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • 在javascript中解析json - 长数字被四舍五入

    我需要解析一个包含长数字的 json 在 java servlet 中生成 问题是长数字被四舍五入 当执行这段代码时 var s x 6855337641038665531 var obj JSON parse s alert obj x
  • Babel 7 Jest Core JS“TypeError:wks不是函数”

    将我的项目升级到 Babel 7 后 通过 Jest 运行测试会抛出以下错误 测试在 Babel 6 中运行没有任何问题 但在 Babel 7 中失败并出现以下错误 TypeError wks is not a function at Ob
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 条件在反应本机生产中失败,但在开发中有效

    我创建了一个反应本机应用程序 我需要通过它进行比较 如果属实 就会执行死刑 问题是 该条件适用于 React Native 开发模式 而不适用于 React Native 生产版本 我使用 firebase 作为数据库 也使用 redux
  • JQuery 图像上传不适用于未来的活动

    我希望我的用户可以通过帖子上传图像 因此 每个回复表单都有一个上传表单 用户可以通过单击上传按钮上传图像 然后单击提交来提交帖子 现在我的上传表单可以上传第一个回复的图像 但第二个回复的上传不起作用 我的提交过程 Ajax 在 php 提交
  • 如何仅在最后一个
  • 处给出透明六边形角度?
  • 我必须制作这样的菜单 替代文本 http shup com Shup 330421 1104422739 My Desktop png http shup com Shup 330421 1104422739 My Desktop png
  • 如何获取浏览器视口中当前显示的内容

    如何获取当前正在显示长文档的哪一部分的指示 例如 如果我的 html 包含 1 000 行 1 2 3 9991000 并且用户位于显示第 500 行的中间附近 那么我想得到 500 n501 n502 或类似的内容 显然 大多数场景都会比
  • 导致回发到与弹出窗口不同的页面

    我有一个主页和一个详细信息页面 详细信息页面是从主页调用的 JavaScript 弹出窗口 当单击详细信息页面上的 保存 按钮时 我希望主页 刷新 是否有一种方法可以调用主页的回发 同时还可以从详细信息页面维护保存回发 Edit 使用win

随机推荐

  • 在 Visual Studio Code 中设置文件“launch.json”的 Python 路径

    我使用 Visual Studio Code 已有几年了 我发现它是一个非常好的 IDE 我用 Python 编程的次数比任何其他语言都多 令我困扰的是我没有抽出时间使用 IDE 的调试器 尽管它是一个功能 按调试播放按钮时出错 Faile
  • dplyr 总结函数返回值何时为向量值?

    The dplyr summarize 函数可以对数据应用任意函数 但函数似乎必须返回标量值 我很好奇是否有一种合理的方法来处理返回向量值的函数 而无需多次调用该函数 这是一个有点愚蠢的最小示例 考虑一个给出多个值的函数 例如 f lt f
  • ubuntu 18.10 - 如何使用 java 安装 JavaFX

    我安装了openjdk8和11 JavaFX 都没有附带 我安装了 openjfx 和 libopenjfx java 软件包 但无法让我的应用程序运行 sudo apt list installed grep jfx WARNING ap
  • 两个geom_points添加图例

    我使用以下代码绘制 2 geom point 图 source http www openintro org stat data arbuthnot R library ggplot2 ggplot geom point aes x yea
  • Hibernate、Java 9 和 SystemException

    我一直在尝试在 Java 9 Spring Boot 1 5 x Maven 项目中运行 Hibernate 5 2 11 应用程序 但缺少类 Caused by java lang NoClassDefFoundError javax t
  • 找不到 com.google.android.gms:strict-version-matcher-plugin:1.1.0

    无法解析配置 类路径 的所有文件 找不到 com google android gms strict version matcher plugin 1 1 0 在以下位置进行了搜索 https jcenter bintray com com
  • 当新值与上一个值相同时 StateFlow 不会发出

    我有一个登录表格 我用StateFlow发送LoginResult 调用API后 来自ViewModel to Activity 在活动中 如果登录失败 我将显示错误对话框 第一次运行良好 但从第二次登录失败后 错误对话框将不再显示 我测试
  • Rails 3.1 间歇性“脚本头过早结束”

    所以我开始将我们的应用程序从 Rails 3 0 9 升级到 Rails 3 1 它在开发环境中运行良好 是时候将其放到临时服务器上了 这样我们就可以运行一些完整的验收测试 但是哦 不 我们正面临着可怕的 内部服务器错误 页面有一半的时间返
  • XML 漏洞

    xml 一直是面向服务的应用程序 SOA 的支柱 并且在未来它将变得非常有用 由于 xml 简单 灵活 因此很容易受到攻击 攻击者可以将其用于自己的目的 因此 一些攻击是强制解析攻击 XML外部实体 XEE 攻击 XML dos xdos
  • 从 PowerShell 调用 exe 并获取有关成功或失败的反馈

    如何在 PowerShell 中运行可执行文件并通过 if 语句确定它是成功还是失败 更具体地说 我试图让 devenv exe 从 PowerShell 脚本构建解决方案 我需要知道它是成功还是失败 失败是指构建失败 并且我假设 deve
  • Ruby 将数组合并为一个字符串

    在 Ruby 中 有没有一种方法可以将所有数组元素组合成一个字符串 数组示例 arr p Hello World p p This is a test p 示例输出 p Hello World p p This is a test p Us
  • 为什么 C++ 中元组的使用不常见?

    为什么似乎没有人在 C 中使用元组 或者Boost元组库 http www boost org doc libs 1 39 0 libs tuple doc tuple users guide html或者 TR1 的标准库 我读过很多 C
  • 将组件对齐到所需位置

    寻求帮助来设计如下所示的布局 我面临的主要挑战是将组件对齐到所需的位置 请参考三个按钮 图标 及其位置 从字面上看 就是发疯 思考如何将它们准确地放置在所需的位置 任何帮助深表感谢 问候 罗尼 由于您使用了 Android 类别 我假设您正
  • 如何使用 JavaScript 触发“isTrusted=true”点击事件?

    我正在尝试使用 Chrome 扩展来模拟用户点击和鼠标移动 例如 在我的内容脚本中 有一个按钮单击 document querySelector SOME SELECTOR click 该行触发具有以下属性的单击事件 MouseEvent
  • Maven原型:修改artifactId

    在进行项目时 我的要求是创建一个模块 该命令将类似于 mvn archetype generate DarchetypeCatalog local DartifactId test module 并且目标应该具有以下文件结构 test mo
  • PJSIP 库中的 TLSv1_2 (TLS1.2) 支持

    我正在使用最新的PJSIP http www pjsip org 我的 Android iOS 应用程序中的库 我想在我的项目中使用 TLSv1 2 连接 PJSIP 支持哪个 TLS 版本 从源代码来看它似乎支持TLSv1 0 有没有办法
  • 如何获取checkbox的值

    如何获取复选框的值 var tb new Ext Toolbar tb add xtype checkbox boxLabel Expand Groups by Default id GetChkBoxValue checked true
  • 应用程序终止自身最暴力的方式是什么(linux)

    我想模拟暴力系统关闭 即在应用程序级别尽可能接近断电 我们正在讨论 Linux 上的 c c 应用程序 我需要应用程序自行终止 目前我看到几个选项 call exit http linux die net man 3 exit call e
  • SortedSet - 存储类对象时的自定义顺序

    我正在考虑用 SortedSet 替换 HashSet 因为它更适合我存储的数据 然而 到目前为止我看到的所有示例都与存储简单对象有关 整数 字符串等 我想为具有多个属性的自定义类实现此功能 但是该类还包含一个我想用作 索引器 的日期 问题
  • 将长时间运行的任务分配到多个帧上的最佳方法是什么?

    我有多个长时间运行的任务 例如超过 10 毫秒 这会影响浏览器的响应能力 最糟糕的事情 例如从文件加载和解析 3D 模型 已经被卸载到 Web Workers 这样它们就不会影响渲染循环 然而 有些任务不容易移植到 Workers 因此必须