非常快的无限循环,不阻塞 I/O

2024-03-30

有没有更快的替代方案window.requestAnimationFrame()对于不阻塞 I/O 的无限循环?

我在循环中所做的事情与动画无关,所以我不在乎下一帧何时准备好,并且我已经读过window.requestAnimationFrame()受到监视器刷新率的限制,或者至少等待直到可以绘制帧。

我也尝试过以下方法:

function myLoop() {
    // stuff in loop
    setTimeout(myLoop, 4);
}

(4是因为这是最小间隔setTimeout较小的值仍默认为 4。)但是,我需要比这更好的分辨率。

还有比这更好的性能吗?

我基本上需要一个非阻塞版本while(true).


有两件事会比这更快地运行setTimeout:

  • process.nextTick https://nodejs.org/api/process.html#process_process_nexttick_callback_args回调(特定于 NodeJS):

    The process.nextTick()方法将回调添加到“下一个刻度队列”。一旦事件循环的当前轮次运行完成,当前在下一个滴答队列中的所有回调将被调用。

    这不是一个简单的别名setTimeout(fn, 0)。它的效率要高得多。它在事件循环的后续滴答中触发任何其他 I/O 事件(包括计时器)之前运行。

  • 承诺结算通知

因此,这些可能是您工具带上的工具,将其中一个或两个与setTimeout达到你想要的平衡。

Details:

您可能知道,给定的 JavaScript 线程在任务队列的基础上运行(规范将其称为作业队列);您可能知道,浏览器中有一个主要的默认 UI 线程,而 NodeJS 运行单个线程。

但实际上,现代实现中至少有两个任务队列:我们都想到的主要一个(其中setTimeout和事件处理程序放置其任务),以及在处理主任务(或“宏任务”)期间放置某些异步操作的“微任务”队列。一旦宏任务完成,这些微任务就会被处理,before主队列中的下一个宏任务 - 即使下一个宏任务在微任务之前排队。

nextTick回调和承诺结算通知都是微任务。因此,调度要么调度异步回调,但该回调将在下一个主要任务之前发生。

我们可以在浏览器中看到setInterval和一个承诺解析链:

let counter = 0;

// setInterval schedules macrotasks
let timer = setInterval(() => {
  $("#ticker").text(++counter);
}, 100);

// Interrupt it
$("#hog").on("click", function() {
  let x = 300000;

  // Queue a single microtask at the start
  Promise.resolve().then(() => console.log(Date.now(), "Begin"));

  // `next` schedules a 300k microtasks (promise settlement
  // notifications), which jump ahead of the next task in the main
  // task queue; then we add one at the end to say we're done
  next().then(() => console.log(Date.now(), "End"));

  function next() {
    if (--x > 0) {
      if (x === 150000) {
        // In the middle; queue one in the middle
        Promise.resolve().then(function() {
          console.log(Date.now(), "Middle");
        });
      }
      return Promise.resolve().then(next);
    } else {
      return 0;
    }
  }
});

$("#stop").on("click", function() {
  clearInterval(timer);
});
<div id="ticker">&nbsp;</div>
<div><input id="stop" type="button" value="Stop"></div>
<div><input id="hog" type="button" value="Hog"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

当您运行该程序并单击Hog按钮,注意计数器显示如何冻结,然后又继续显示。这是因为提前安排了 300,000 个微任务。另请注意我们编写的三个日志消息上的时间戳(它们不会出现在代码片段控制台中,直到宏任务显示它们,但时间戳向我们显示它们的记录时间)。

所以基本上,您可以安排一堆微任务,并定期让这些微任务运行完并运行下一个宏任务。


Note: 我用过setInterval对于代码片段中的浏览器示例,但是setInterval,具体来说,对于使用 NodeJS 的类似实验来说可能不是一个好的选择,因为 NodeJS 的setInterval与浏览器中的有点不同,并且具有一些令人惊讶的计时特征。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

非常快的无限循环,不阻塞 I/O 的相关文章

随机推荐

  • 链接到外部 css 文件

    我一直在尝试将我在本地计算机中创建的 css 文件链接到我的 html 代码 但它似乎不起作用 我们应该在 html 代码中保存想要链接的 css 文件 或者我们应该如何链接到该文件 作为一个例子 我发布了这个 html 代码
  • 功能证明 (Haskell)

    我没能读懂 RWH 我命令没有人放弃Haskell 函数式编程的技巧 现在我对第 146 页上的这些功能证明很好奇 具体来说 我试图证明 8 5 1sum reverse xs sum xs 我可以做一些归纳证明 但后来我陷入困境 HYP
  • opencv无法保存视频

    我正在尝试使用 opencv 写入方法保存视频 但视频保存为 0 kb 我的代码出了什么问题 import cv2 cap cv2 VideoCapture k1 mp4 assert cap isOpened fgbg cv2 bgseg
  • 使用 CUDA 进行希尔伯特变换

    为了对一维数组进行希尔伯特变换 必须 对数组进行 FFT 将数组的一半加倍 将另一半归零 反 FFT 结果 我正在使用 PyCuLib 进行 FFTing 到目前为止我的代码 def htransforms data N data shap
  • Firebase 实时数据库的分页

    我一直在尝试寻找一种为 Firebase 实时数据库进行分页的方法 我看到很多关于 Cloud Firestore 分页的教程 文章 但没有看到关于实时数据库的分页 下面是我的代码及其按预期工作 谁能指出我添加分页的正确方向 如果可能的话
  • 使用 Gradle 将模块化库发布到 Maven

    假设我使用 Gradle 进行模块化库开发 在我的根项目中我有子项目geometry algorithms visualizer 我想发布每个的 jar 工件 至于现在在我的根build gradle我有以下部分 apply plugin
  • MVC 模型对象、域对象和 DTO 之间有什么区别

    MVC 模型对象 域对象和 DTO 之间有什么区别 我的理解是 MVC 模型对象 对要由相应视图显示的数据进行建模 它可能不会直接映射到域对象 即可能包含来自一个或多个域对象的数据 客户端 可能包含业务逻辑 例如 验证 计算属性等 没有持久
  • 比较()中的空字段该怎么办?

    在Java中 我使用一个类 其中一些字段可以null 例如 class Foo String bar 我想为这个类写一个BarComparator private static class BarComparator implements
  • 如何使用 VBA sendkeys 打印或发送大括号 ( )

    我有以下代码 但不发送大括号 sendkeys a script sh true 但它作为 a script sh 发送 大括号缺失 Try this SendKeys a script sh True 例如 Sub Sample Dim
  • Adobe Flash Builder 能否用于调试和分析 OpenLaszlo SWF10/SWF11 应用程序?

    我读过 Adob e 的Flash Builder 4 0 支持 ActionScript 3 的分析 http help adobe com en US flashbuilder using WS6f97d7caa66ef6eb1e63e
  • 为什么 Hadoop 中正确的缩减数量是 0.95 或 1.75?

    hadoop 文档指出 正确的归约次数似乎是 0 95 或 1 75 乘以 mapred tasktracker reduce tasks maximum 0 95 所有的减少都可以立即启动并开始 地图完成时传输地图输出 用1 75更快 节
  • UML 类图概念、规范、实现

    我目前正在阅读 Martin Fowler 的 UML Distilled 我刚刚介绍了有关类图的部分 他在其中强调了在对类图进行建模之前理清自己的观点的必要性 然而 在实际绘制类图时 我对它的实际外观有点困惑 例如 我理解理论含义会改变关
  • Symfony2 自定义表单字段

    我对 Symfony 很陌生 所以问题可能看起来有点简单 但我需要帮助 我已经生成了新的捆绑包 我添加了一条新路线Me MyBundle Resources config routing yml my homepage pattern de
  • jQuery:append()对象,用delay()删除()它

    这有什么问题吗 body append div class message success Upload successful div message delay 2000 remove 我想将成功消息附加到我的 html 文档中 但只持续
  • 通过反射获取对象

    我正在寻找 C 中的机制 如下所示 Car car1 Car car2 Car car Car SomeMechanism Get car1 car1 和 car2 是字段 所以我想得到一些带有反射的对象 而不是类型 我怎样才能在c 中做到
  • 如何忽略 Web 浏览器中的脚本错误

    当我关闭使用网络浏览器的应用程序时会发生什么 以下网址使用flash播放器 一切正常 此错误在应用程序关闭时显示 我该如何忽略它 我知道为时已晚 但我觉得我对这个问题有一个聪明的答案 使用这个 它对我来说很有效 webBrowser Scr
  • 多重处理:类型错误:“int”对象不可迭代

    我正在使用multiprocessingPython 3 中的模块 但由于某种原因 它不断抛出TypeError int object is not iterable当我运行程序时 这就是我所做的 def main i global url
  • mod_wsgi 无法连接 WSGI 守护进程

    我正在使用 Easy apache 4 mod wsgi 和 Python 3 5 当我在服务器中调用 Django 项目时 出现以下错误 13 Permission denied mod wsgi pid 24223 Unable to
  • 平移多个 Y 轴之一以获取高图

    我是 highchart javascript 的新手 而且我没有样品来展示它 但我见过图表有两个 Y 轴 左轴和右轴 我可以上下拖动一个轴而不影响另一个轴 该图表可能包含一些系列数据 我见过构建的插件 http www highchart
  • 非常快的无限循环,不阻塞 I/O

    有没有更快的替代方案window requestAnimationFrame 对于不阻塞 I O 的无限循环 我在循环中所做的事情与动画无关 所以我不在乎下一帧何时准备好 并且我已经读过window requestAnimationFram