最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

Node.js 多进程处理CPU密集任务的实现

来源:懂视网 责编:小采 时间:2020-11-27 21:56:15
文档

Node.js 多进程处理CPU密集任务的实现

Node.js 多进程处理CPU密集任务的实现:Node.js 单线程与多进程 大家都知道 Node.js 性能很高,是以异步事件驱动、非阻塞 I/O 而被广泛使用。但缺点也很明显,由于 Node.js 是单线程程序,如果长时间运算,会导致 CPU 不能及时释放,所以并不适合 CPU 密集型应用。 当然,也不是没有办法解决这个问
推荐度:
导读Node.js 多进程处理CPU密集任务的实现:Node.js 单线程与多进程 大家都知道 Node.js 性能很高,是以异步事件驱动、非阻塞 I/O 而被广泛使用。但缺点也很明显,由于 Node.js 是单线程程序,如果长时间运算,会导致 CPU 不能及时释放,所以并不适合 CPU 密集型应用。 当然,也不是没有办法解决这个问

查找 500 次需要 44 秒,太慢了。可想而知如果位置更大,数量更多...

那我们来尝试用多进程试试 ⬇️

多进程

采用 cluster 模块,Master-Worker 模式来测试

共 3 个 js,分别为主线程代码:master.js、子进程代码:worker.js、入口代码:cluster.js(入口可无需单独写一个 js、这里是为了看起来更清楚一些)

主线程代码:master.js

const cluster = require("cluster");
const numCPUs = require("os").cpus().length;

// 设置子进程执行程序
cluster.setupMaster({
 exec: "./worker.js",
 slient: true
});

function run() {
 // 记录开始时间
 const startTime = Date.now();
 // 总数
 const totalCount = 500;
 // 当前已处理任务数
 let completedCount = 0;
 // 任务生成器
 const fbGenerator = FbGenerator(totalCount);

 if (cluster.isMaster) {
 cluster.on("fork", function(worker) {
 console.log(`[master] : fork worker ${worker.id}`);
 });
 cluster.on("exit", function(worker, code, signal) {
 console.log(`[master] : worker ${worker.id} died`);
 });

 for (let i = 0; i < numCPUs; i++) {
 const worker = cluster.fork();

 // 接收子进程数据
 worker.on("message", function(msg) {
 // 完成一个,记录并打印进度
 completedCount++;
 console.log(`process: ${completedCount}/${totalCount}`);

 nextTask(this);
 });

 nextTask(worker);
 }
 } else {
 process.on("message", function(msg) {
 console.log(msg);
 });
 }

 /**
 * 继续下一个任务
 *
 * @param {ChildProcess} worker 子进程对象,将在此进程上执行本次任务
 */
 function nextTask(worker) {
 // 获取下一个参数
 const data = fbGenerator.next();
 // 判断是否已经完成,如果完成则调用完成函数,结束程序
 if (data.done) {
 done();
 return;
 }
 // 否则继续任务
 // 向子进程发送数据
 worker.send(data.value);
 }

 /**
 * 完成,当所有任务完成时调用该函数以结束程序
 */
 function done() {
 if (completedCount >= totalCount) {
 cluster.disconnect();
 console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
 console.info(`任务完成,用时: ${Date.now() - startTime}ms`);
 console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
 }
 }
}

/**
 * 生成器
 */
function* FbGenerator(count) {
 var n = 35;
 for (var i = 0; i < count; i++) {
 yield n;
 }
 return;
}

module.exports = {
 run
};

1.这里是根据当前电脑的逻辑 CPU 核数来创建子进程的,不同电脑数量也会不一样,我的 CPU 是 6 个物理核数,由于支持超线程处理,所以逻辑核数是 12,故会创建出 12 个子进程

2.主线程与子进程之间通信是通过send方法来发送数据,监听message事件来接收数据

3.不知道大家有没有注意到我这里使用了 ES6 的 Generator 生成器来模拟生成每次需要查找的斐波那契数位置(虽然是写死的 😂,为了和上面的单线程保证统一)。这么做是为了不让所有任务一次性扔出去,因为就算扔出去也会被阻塞,还不如放在程序端就给控制住,完成一个,放一个。

子进程代码:worker.js

function fibonacci(n) {
 if (n == 0 || n == 1) {
 return n;
 } else {
 return fibonacci(n - 1) + fibonacci(n - 2);
 }
}

// 接收主线程发送过来的任务,并开始查找斐波那契数
process.on("message", n => {
 var res = fibonacci(n);
 // 查找结束后通知主线程,以便主线程再度进行任务分配
 process.send(res);
});
入口代码:cluster.js
// 引入主线程js,并执行暴露出来的run方法
const master = require("./master");
master.run();

执行node cluster.js 查看结果

在我的电脑上显示结果为10724ms(电脑配置不同也会有差异)。

process: 500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
任务完成,用时: 10724ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏

结果

进过上面两种方式的对比,结果很明显,多进程处理速度是单线程处理速度的 4 倍多。而且有条件的情况下,如果电脑 CPU 足够,进程数更多,那么速度也会更快。

如果有更好的方案或别的语言能处理你的需求那就更好,谁让 Node.js 天生就不适合 CPU 密集型应用呢。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

Node.js 多进程处理CPU密集任务的实现

Node.js 多进程处理CPU密集任务的实现:Node.js 单线程与多进程 大家都知道 Node.js 性能很高,是以异步事件驱动、非阻塞 I/O 而被广泛使用。但缺点也很明显,由于 Node.js 是单线程程序,如果长时间运算,会导致 CPU 不能及时释放,所以并不适合 CPU 密集型应用。 当然,也不是没有办法解决这个问
推荐度:
标签: 多进程 node.js node
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top