节点JS单线程与多线程(CPU利用率:有什么区别吗?

Node JS single Threaded Vs MultiThreading (CPU Utilization : Any difference ? )

本文关键字:什么 区别 利用率 CPU 单线程 JS 多线程 节点      更新时间:2023-09-26

我最近开始阅读很多关于 Node JS 的文章,从差异化的角度来看,我无法清楚地理解的一件事是异步与同步调用处理 I/O 的真正区别是什么。

据我了解,在多线程同步环境中,如果启动I/O,正在运行的线程将被抢占并移回等待状态。所以本质上这与 NodeJS 异步 I/O 调用发生的情况相同。在 Node JS 中,当调用 I/O 时,I/O 操作将移出当前正在运行的线程,并发送到事件解复用器进行完成和通知。I/O 完成后,回调方法将推送到事件队列进行进一步处理。

所以,我看到的唯一区别是,在 Node JS 中,我们正在节省内存(由于每个线程拥有多个调用堆栈)和 CPU(由于没有上下文切换而保存)。如果我只考虑我有足够的内存来购买,仅由于上下文切换而节省的CPU是否会产生巨大的性能差异?

如果我的上述理解不正确,那么 Java 线程与节点 JS w.r.t 之间的 I/O 处理与保持 CPU 繁忙而不浪费 CPU 周期有什么不同。我们是使用 Node JS 仅节省上下文切换 CPU 周期,还是还有更多?

根据回复,我想添加另一个场景:

请求

A,请求 B 同时来到 J2ee 服务器。在此多线程环境中,每个请求需要 10 毫秒才能完成。在 10 毫秒中,5 毫秒用于执行代码逻辑以计算某些逻辑,5 毫秒用于从 DBMS 中提取大型数据集的 I/O。对 DBMS 的调用是代码的最后一行,之后应将响应发送到客户端。

如果将同一应用程序转换为节点JS应用程序,则可能会发生这种情况

  1. 请求 A 来了,5 毫秒用于处理请求。

  2. DBMS 调用是从代码命中,但它是非阻塞的。所以一个回调方法被推送到事件队列。

  3. 5 毫秒后,请求 B 将再次送达请求 B 被推送到事件队列以完成 I/O。请求 B处理需要 5 毫秒。
  4. 事件循环运行,拾取回调请求 A 的处理程序,然后将响应发送到客户端。所以响应在 10 毫秒后发送,因为请求 A 和请求 B 都花了 5毫秒,用于同步代码块处理。

现在在这种情况下节省的时间在哪里?除了上下文切换和创建 2 个线程。无论如何,Req A 和 Req B 在 Node JS 上都需要 10 毫秒。?

据我了解,在多线程同步环境中,如果I/O 启动,正在运行的线程被抢占并移回 等待状态。所以本质上这与 NodeJS 发生的情况相同 异步 I/O 调用

不,在 NodeJS 中,异步 I/O 调用是非阻塞 I/O。这意味着一旦线程进行了 I/O 调用,它就不会等待 I/O 完成并继续执行下一个语句/任务。

一旦 I/O 完成,它就会从事件循环队列中选取下一个任务,并最终执行在进行 I/O 调用时提供给它的回调处理程序。

如果我只是认为我有足够的内存来购买,是否保存 仅由于上下文切换,CPU就使巨大的性能 差异?

除此之外,储蓄也来自这两件事

  • 无需等待 I/O 完成
  • 由于线程是有限的,因此系统的容量不受它可以创建多少线程的限制。

除了上下文切换和创建 2 个线程。Req A & Req B 无论如何,两者都需要 10 毫秒的 Node JS。?

您在这里打折了一件事 - 线程在特定间隔后一个接一个地收到两个请求。因此,如果一个线程需要 10 秒,那么它将需要一个新线程来执行第二个请求。将其扩展到数千个请求,并且您的操作系统必须创建数千个线程来处理如此多的并发用户。请参考这个类比。