使用 setTimeout 拆解一些 CPU 密集型的执行任务

简介: 使用 setTimeout 拆解一些 CPU 密集型的执行任务

未优化之前的版本:

let i = 0;
let start = Date.now();
function count() {
  // do a heavy job
  for (let j = 0; j < 1e9; j++) {
    i++;
  }
  alert("Done in " + (Date.now() - start) + 'ms');
}
count();

上述 count 函数里的 for 循环的 i 累加,是一个 CPU 密集型任务,在执行完毕之前,JavaScript 引擎任务队列里的其他任务,没有机会得到执行。


优化版本

将 i 从 1 累加到 1e9 的任务,拆解成 1000 个小的子任务。每个子任务执行完毕之后,调用 setTimeout 调度自身,这样任务队列里其他任务有机会得到执行。

let i = 0;
let start = Date.now();
function count() {
  // do a piece of the heavy job (*)
  do {
    i++;
  } while (i % 1e6 != 0);
  if (i == 1e9) {
    alert("Done in " + (Date.now() - start) + 'ms');
  } else {
    setTimeout(count); // schedule the new call (**)
  }
}
count();
  • 第一轮任务执行:i=1…1000000
  • 第二轮任务执行:i=1000001…2000000

以此类推。


现在,如果在引擎忙于执行第 1 部分时出现新的辅助任务(例如 onclick 事件),它会排队,然后在第 1 部分完成时执行,然后再执行下一部分。 在 count 执行之间,使用 setTimeout 定期返回事件循环,为 JavaScript 引擎提供了调度执行其他任务的机会,以对其他用户操作做出反应。

let i = 0;
let start = Date.now();
function count() {
  // move the scheduling to the beginning
  if (i < 1e9 - 1e6) {
    setTimeout(count); // schedule the new call
  }
  do {
    i++;
  } while (i % 1e6 != 0);
  if (i == 1e9) {
    alert("Done in " + (Date.now() - start) + 'ms');
  }
}
count();

为浏览器脚本拆分 CPU 密集型任务的另一个好处是我们可以显示进度指示。

如前所述,只有在当前运行的任务完成后才会绘制对 DOM 的更改,无论当前运行的任务需要多长时间才能执行完毕。

下面是一个例子:

<div id="progress"></div>
<script>
  function count() {
    for (let i = 0; i < 1e6; i++) {
      i++;
      progress.innerHTML = i;
    }
  }
  count();
</script>

对 i 的更改要等到函数执行完成后才会显示,所以我们只会看到最后一个值。

但我们也可能想在任务期间展示一些东西,例如一个进度条。

如果我们使用 setTimeout 将繁重的任务拆分为多个部分,那么 i 会在多个部分执行之间绘制出来。

<div id="progress"></div>
<script>
  let i = 0;
  function count() {
    // do a piece of the heavy job (*)
    do {
      i++;
      progress.innerHTML = i;
    } while (i % 1e3 != 0);
    if (i < 1e7) {
      setTimeout(count);
    }
  }
  count();
</script>
相关文章
|
10月前
|
SQL 缓存 人工智能
CPU密集型和IO密集型任务的权衡:如何找到最佳平衡点
CPU密集型与I/O密集型是在计算机上执行任务的两种策略,在并发执行任务场景下,我们需要选择使用多线程或多进程; 如果是IO密集型任务,使用多线程,线程越多越好; 如果是CPU密集型任务,使用多进程,线程数量与CPU核心数匹配。
|
4月前
Dataphin中运行任务所需的资源不仅包括CPU,还有内存
【1月更文挑战第11天】【1月更文挑战第53篇】Dataphin中运行任务所需的资源不仅包括CPU,还有内存
33 2
|
7月前
|
存储 调度
cpu 中控制单元执行的任务分析
cpu 中控制单元执行的任务分析
141 0
|
8月前
|
JavaScript 测试技术 调度
CPU密集型任务会阻塞 Node.js 吗
CPU密集型任务会阻塞 Node.js 吗
58 0
|
消息中间件 存储 缓存
【操作系统入门到成神系列 五】CPU 是如何执行任务的
【操作系统入门到成神系列 五】CPU 是如何执行任务的
【操作系统入门到成神系列 五】CPU 是如何执行任务的
|
4天前
|
Linux
Linux rsyslog占用内存CPU过高解决办法
该文档描述了`rsyslog`占用内存过高的问题及其解决方案。
27 4
|
27天前
|
移动开发 运维 监控
掌握Linux运维利器:查看CPU和内存占用,轻松解决性能问题!
掌握Linux运维利器:查看CPU和内存占用,轻松解决性能问题!
|
28天前
|
监控 Python
【python】实现cpu/内存监控的功能(非常简单)
【python】实现cpu/内存监控的功能(非常简单)
|
29天前
|
Linux
Linux 查看进程PID和线程CPU和内存占用情况
Linux 查看进程PID和线程CPU和内存占用情况
22 0
|
2月前
|
运维 监控 网络协议
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
62 0

相关实验场景

更多