我只是观看下面的视频︰简介 Node.js ,仍不了解如何获得的速度优势。

主要是,一方面 Ryan Dahl (Node.js 的创建者) 说 Node.js 是基于而不是基于线程的事件循环。线程开销很大,只留给的并发编程使用专家。

以后,他再显示了体系结构堆栈的 Node.js 哪有基础 C 实现内部有它自己的线程池。显然 Node.js 开发人员永远不会甩掉它们自己的线程或...直接使用线程池使用异步回调。我得多了解。

什么我不懂,Node.js 仍使用线程...点也是只隐藏 50 呢,这是更快 50 的人请求文件 (没有在内存) 的实现然后 50 所需的线程不是吗?

由于其具有内部托管 Node.js 开发人员不需要代码线程的详细信息,但它仍在使用线程来处理 IO (阻塞) 的基础唯一区别是文件的请求。

因此不您实际上只采取一个问题 (线程) 和隐藏它,而该问题仍然存在︰ 主要是多线程、 上下文切换,...死锁等?

必须有一些仍不明白这里的详细信息。

2010-09-02 17:53:47
问题评论:

我倾向于同意您的索赔有些过度简化。我相信节点的性能优势归结为两点︰ 1) 和实际的线程都包含在非常低的级别,并因此保持不受约束的大小和数量,从而简化了线程同步;2) 操作系统级"转换" select()通过将线程上下文交换比快。

请参阅此stackoverflow.com/questions/24796334/...

回答:

有实际的一些不同的事情正在这里 conflated。但是,它使用 meme 线程都只是很难启动。因此,如果它们硬,则更可能的是,当使用线程 1) 由于错误中断并 2) 没有尽可能有效地使用它们。(2) 是的一个正在询问有关。

想约他提供,其中请求进入时,运行某些查询时,示例之一,进行一些处理的结果。如果您编写它的标准过程的方式,代码可能如下所示︰

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

如果传入的请求引起的您可以创建一个新线程运行上面的代码,您必须坐在那儿, query()运行时不执行任何操作时在所有的线程。(apache,Ryan,根据使用单个线程来满足原始的请求而 nginx 因为它不是自己所谈论的情况下在 outperforming 它。)

现在,如果您真的聪明,会表达环境无法熄灭,当您运行查询时执行其他操作的方式上面的代码︰

query( statement: "select smurfs from some_mushroom", callback: go_do_something_with_result() );

这基本上是什么 node.js 正在执行的操作。您正在基本上装修,由于语言和环境,因此是非常方便的一种关于闭包 — 环境可以是关于哪些运行过程中,聪明的方式代码点和时间。以这种方式,node.js 不是的局限性,它发明了异步 I/O (没有任何人声称这样的内容),但它是新的因为它表达的方式也是略有不同。

注意︰ 当我说环境可以是关于哪些运行聪明和时特别明白我的意思是,它用来启动一些 I/O 的线程现在可用来处理其他请求或某种计算可以进行并行,或启动某些其他并行 I/O。 (我不确信复杂的节点足以启动同一请求更多的工作但您已领会了要旨。)

好了,我肯定可以看到如何这可以提高性能,因为听起来我好像能够出 CPU 最大,因为没有任何线程或只等待 IO 返回 Ryan 采取了什么措施有效地找到方法来关闭所有的间隙以便执行堆栈。

是的我想说一件事是它是不能让他找到一种方法来封闭间隙︰ 它不是新的模式。不同的是,他使用 Javascript 程序员可表达他们的程序更方便这种异步的方式。可能是 nitpicky 的详细信息,但仍...

值得指出的大量 I/O 任务,节点使用任何内核级异步 I/O 是可用 (epoll,kqueue,/开发/调查中,任何) 的 api

我仍不确定,我完全理解它。如果我们考虑内的 web 请求 IO 操作花大部分时间来处理该请求所需的那些,如果为每个 IO 操作创建一个新线程,然后 50 进入快速连续的请求我们可能将 50 线程并行运行和执行其 IO 部件。从标准 web 服务器的区别是,在整个请求线程上执行,而 node.js 只是在它 IO 的部件,但这是花大部分时间并使线程一直等待的部分。

@SystemParadox 指出的多谢。我实际上做一些研究主题最近和问题实际上是异步 I/O,在内核级别上,正确实施后不会在执行异步 I/O 操作的同时使用线程。而是调用的线程被释放只要启动的 I/O 操作,并且当 I/O 操作已完成且可用的线程执行回调。因此 node.js 可以用 50 个 I/O 操作,在 (几乎) 并行使用运行 50 个并发请求是正确实施仅在一个线程如果异步 I/O 操作的支持。

注意 !这是旧的答案。尽管很粗略大纲中仍然如此,某些详细信息可能已更改由于在过去几年中节点的快速发展。

因为,它使用线程︰

  1. O_NONBLOCK 选项的 open () 上的文件不起作用.
  2. 有第三方库,它们不能提供非阻塞 IO。

来隐藏非阻塞 IO,线程都需要︰ 不要在一个单独的线程阻塞 IO。它是一个丑陋的解决方案,并会产生多大的开销。

它会更糟,在硬件级别上︰

  • 使用DMA CPU 以异步方式减轻 IO。
  • IO 设备和内存之间直接传输数据。
  • 内核环绕这中同步阻塞系统调用。
  • Node.js 包装在一个线程阻塞的系统调用。

这是只是出于愚蠢而且效率低下。但它至少工作 !我们可以享受 Node.js,因为它会隐藏背后的事件驱动的异步体系结构的丑陋和繁琐细节。

也许有人会实现 O_NONBLOCK 文件将来?...

编辑︰这与朋友介绍,他告诉我,线程的替代选择轮询︰ 指定超时值为 0,对返回的文件描述符执行 IO,(既然能够保证不阻止)。

我担心我"犯错"在这里,如果是这样删除我,我深表歉意。特别是,我没有看到如何创建已导致有些人的灵巧小批注。但是,我有很多顾虑/观察在此线程上进行。

1) 中受欢迎的回答之一的伪代码中的注释的元素

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

是实质上是伪造的。如果计算线程,则它不全部拇指,进行必要的工作。如果,另一方面,只等待完成 IO,那么它使用 CPU 时间内核中的线程控制基础架构的整个点是,CPU 有用的东西要做。作为的"twiddle 拇指"的唯一办法建议,此处就是创建一个轮询循环,并具有编码实际 web 服务器的任何人是足够 inept,要做到这一点。

2)"线程都硬",只有在数据共享的上下文中有意义。如果您有实质上的独立线程如是这种情况,处理请求,然后线程一般而言简单,只是代码如何处理一个作业,并坐非常了解,它将处理的多个请求,并且每个将会有效地独立的线性流程组成的独立 web 时。就个人而言,我会风险,对于大多数程序员来说,学习的闭包/回调机制是复杂,而不仅仅只编写代码的顶部到底部线程版本。(是的如果线程间通信时,生命很难获取很快,但是然后我是 unconvinced,但闭包/回调机制真正更改,它只是限制您的选项,因为这种方法是使用线程仍可达到。不管怎样,这是无关确实这里的整个其他讨论)。

3) 到目前为止,没有人提供了任何实际证据,为什么一种特定类型的上下文切换是多或少花费的时间比其他任何类型。我创建 (在小范围内对于嵌入式控制器,没什么作为"真正的"操作系统那么难懂) 的多任务内核中的经验表明,这不是这种情况。

4) 所有的图,我迄今为止看过自称显示多少更快的节点,是不是其他 webservers 出现严重缺陷,但是,他们正在以一种间接说明我会明确接受的节点的优点之一缺陷 (,并不意味着无关紧要)。节点不会看起来它需要 (也不甚至允许,实际上) 调整。如果您有一个线程的模型,您需要创建足够的线程来处理预期的负载。错误,这样,您最终将得到性能较差。如果有太少的线程,然后 CPU 处于空闲状态,但无法接受更多的请求,创建线程太多,并会浪费内核内存,并在 Java 环境中,您将还会浪费主堆内存。现在,对于 Java,浪费堆是第一,最好,办法螺钉系统的性能,因为有效的垃圾回收 (当前,这可能会更改与 G1,但似乎,陪审团仍然出早期 2013 年该点上至少是) 取决于有大量空闲堆。因此,还有一个问题是,太少的线程进行调整,有空闲的 Cpu 和吞吐量降低,它与太多,并且它停顿在其他方面的调整。

5) There is another way in which I accept the logic of the claim that Node's approach "is faster by design", and that is this. Most thread models use a time-sliced context switch model, layered on top of the more appropriate (value judgement alert :) and more efficient (not a value judgement) preemptive model. This happens for two reasons, first, most programmers don't seem to understand priority preemption, and second, if you learn threading in a windows environment, the timeslicing is there whether you like it or not (of course, this reinforces the first point; notably, the first versions of Java used priority preemption on Solaris implementations, and timeslicing in Windows. Because most programmers didn't understand and complained that "threading doesn't work in Solaris" they changed the model to timeslice everywhere). Anyway, the bottom line is that timeslicing creates additional (and potentially unnecessary) context switches. Every context switch takes CPU time, and that time is effectively removed from the work that can be done on the real job at hand. However, the amount of time invested in context switching because of timeslicing should not be more than a very small percentage of the overall time, unless something pretty outlandish is happening, and there's no reason I can see to expect that to be the case in a simple webserver). So, yes, the excess context switches involved in timeslicing are inefficient (and these don't happen in kernel threads as a rule, btw) but the difference will be a few percent of throughput, not the kind of whole number factors that are implied in the performance claims that are often implied for Node.

不管怎样,道歉的所有长和 rambly,但我确实觉得,到目前为止,讨论还没有证明任何东西,并且很高兴地听到某人在任何一种情况︰

为什么节点会更好) 的真正解释 (之外哪项 (差优化) 中的第一个我相信上面概述了我的两个方案是到目前为止我看到的所有测试的真正解释。([编辑] 实际上,越多考虑到它,越多我想知道是否使用大量的堆栈的内存可能会很重要在此处。默认的堆栈大小的现代线程往往是相当巨大的但基于闭包的事件系统分配内存应该只需要什么)

b) 真实的性能基准,实际上到选择的服务器线程提供一个公平的机会。至少该说一句,我不得不停止相信,索赔实质上是假的; > ([编辑] 可能是相当强,比我预期的位置,但我不要认为充其量,不完整的说明,提供的性能优点,并显示基准是不合理)。

Cheers 白

线程的问题︰ 他们需要的 RAM。几个几千个线程可以运行非常繁忙的服务器。Node.js 避免线程和 thusly 是效率更高。效率不是通过更快地运行代码。如果代码或事件循环的线程中运行并不重要。对于 CPU 是相同。但做掉我们保存 RAM 的线程︰ 一个堆栈,而不是几个千叠。并且我们还可以保存上下文切换。

但与线程未离开执行节点。它仍然使用这些内部的 IO 任务,这是请求需要何种多数 web。

此外节点存储回调的闭包在 RAM 中,因此我可以看到它在 wins。

我不理解什么是,Node.js 仍使用线程的点。

Ryan (大部分 node.js 使用非阻塞 IO) 阻塞该部件使用线程因为某些部分令人抓狂硬写入非阻塞。但我相信 Ryan 的愿望是让一切非阻塞。幻灯片 63(internal design)您看到 Ryan 使用非阻塞eventloop libev(抽象化异步事件通知的库)。由于事件循环 node.js 需要较少的可减少上下文切换的线程、 内存消耗等。

线程只能用于处理无任何异步的设施,像stat()一样的函数.

始终阻止stat()函数,以便 node.js 需要使用一个线程来执行实际的调用而不会阻塞主线程 (事件循环)。可能,如果您不需要调用这些类型的函数将以往任何时候都不使用任何线程池中的线程。

请输入您的翻译

How is Node.js inherently faster when it still relies on Threads internally?

确认取消