赞
踩
对于 web worker 的数量,需要根据具体场景来判断,一般来说:
不要创建太多 web worker,因为每个 web worker 都会占用内存和其他资源。通常不超过 10 个是比较合适的。
根据 CPU 核心数设置 web worker 数量。如果 CPU 有 4 核,那么 4-6 个 web worker 可能是不错的选择。这样可以最大限度利用 CPU 资源,同时不会造成过多资源消耗。
根据任务性质设置。如果是 CPU 密集型任务,可以根据 CPU 核心数设置更多 web worker;如果是 IO 密集型任务,则数量不宜太多,否则可能造成过多的线程上下文切换,影响性能。
CPU 密集型任务:比如计算 Fibonacci 数列、素数判断、图片滤镜处理等。这些任务可以开启 4-6 个 web worker,利用多核 CPU 的计算能力。
IO 密集型任务:比如读取文件、发送 AJAX 请求、WebSocket 通信等。这些任务开启 2-3 个 web worker 就足够,避免过多线程切换影响性能。
可以动态调整 web worker 数量。比如根据系统负载情况,可以动态创建或终止 web worker,以达到最优的线程数量。
比如一个图像编辑网站,当用户执行高消耗操作如图片滤镜或特效时可以临时增加 2-3 个 web worker,操作结束后再关闭这些额外的 web worker。
也可以对不同任务设置不同数量的 web worker。比如 CPU 密集型任务设置更多,IO 密集型任务设置较少。
在一个网站中,用来处理 CPU 密集型数据分析任务的可以开启 4-6 个 web worker;用来维护 WebSocket 连接的只开启 2-3 个 web worker。
避免使用太少的 web worker,否则无法发挥多线程的优势,甚至可能比单线程还慢。至少 2-3 个以上比较合适。
比如一个基础的网站,有一些定时异步任务需要执行,只开启 1 个 web worker 效果可能不佳,这个时候可以开启 2-3 个 web worker 来执行这些异步任务,资源消耗不高但可以带来明显性能提升。
总之,web worker 的数量是需要根据具体应用场景来灵活调整的。设置太少无法发挥优势,设置太多又会造成资源浪费。根据上面几点原则,寻找最优数量是一个实践过程。
对于 IO 密集型任务,推荐使用 2-3 个线程:
IO 操作非常依赖系统资源,如果使用太多线程来进行 IO,很容易导致资源竞争和线程切换,影响性能。
大多数 IO 操作都需要等待数据从外部来源获取,这会导致线程阻塞。如果有太多等待 IO 的线程,会非常浪费 CPU 和内存资源。
客户端网络条件和服务器性能也会对 IO 速度产生 bottleneck。即使创建更多线程,也无法改变这个 bottleneck,所以增加线程数量不能线性提高性能,甚至可能产生反效果。
大部分 IO 操作都是顺序阻塞的,更适合使用单线程或少量线程来完成。使用过多线程只会增加线程管理的开销,影响整体效率。
综上,IO 密集型任务主要依赖外部系统资源与网络条件,单线程或少量线程往往已经可以达到足够好的效果。使用过多线程反而可能会增加资源开销,影响性能。
所以对于一般的 IO 密集型 web 应用,推荐:
不要超过 2-4 个 web worker,甚至主线程就可以处理
可以使用Node.js之类的后端框架,他们使用单线程模型,更适合IO密集型任务
尽量减少线程切换,避免阻塞线程,这需要对程序流程进行优化
在必要时可以动态增加线程,但数量不宜太多
利用事件驱动和异步IO来避免阻塞,提高程序效率
总之,对IO密集型任务,质优于量。单线程或少线程,减少线程切换和竞争,提高单线程效率,这些策略往往更为重要
附:前端获取电脑 CPU 核心数可以通过以下方式:
let cpus = navigator.hardwareConcurrency;
console.log(cpus); // 4
navigator.hardwareConcurrency 返回电脑 CPU 核心数。
let cpus;
const worker = new Worker('cpus.js');
worker.onmessage = function(e) {
cpus = e.data;
console.log(cpus); // 4
}
// cpus.js
let cpus = navigator.hardwareConcurrency;
postMessage(cpus);
在 web worker 里获取,然后 postMessage 发送给主线程。
let start = performance.now();
let cpus = 0;
while (performance.now() - start < 500) cpus++;
console.log(cpus); // 4
利用占用 CPU 的循环来统计循环次数,从而推算出 CPU 核心数。这三种方式在现代浏览器下均可使用,具体支持可以参考 MDN 文档。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。