![]() |
1
142
实际上,这里有一些不同的东西被混为一谈。但从模因开始,线程是非常困难的。因此,如果它们很难使用,那么在使用线程时,更有可能1)由于错误而中断,2)没有尽可能有效地使用它们。(2) 就是你要问的那个。 想一想他给出的一个例子,其中一个请求进来,你运行一些查询,然后对结果做一些事情。如果以标准过程方式编写,代码可能如下所示:
现在,如果您真的很聪明,您可以用一种方式来表达上面的代码,在运行查询时,环境可以关闭并执行其他操作:
这基本上是什么节点.js他在做什么。你基本上是在装饰——由于语言和环境的原因,装饰的方式很方便,因此也就是闭包的要点——你的代码是这样一种方式,环境可以很清楚地知道什么时候运行,什么时候运行。那样的话,节点.js不是吗 新的 从某种意义上说,它发明了异步I/O(并不是说有人声称这样做),但它是新的,因为它的表达方式有点不同。
|
![]() |
2
32
注意! 这是一个古老的答案。虽然大致上还是这样,但由于Node在过去几年的快速发展,一些细节可能已经发生了变化。 它使用线程是因为:
要伪造非阻塞IO,线程是必要的:在单独的线程中执行阻塞IO。这是一个丑陋的解决方案,并造成了很大的开销。 硬件方面更糟糕:
也许将来有人会为文件实现O\u NONBLOCK?。。。 我和一个朋友讨论过这个问题,他告诉我线程的另一种选择是使用 select :在返回的文件描述符上指定超时0和do IO(现在保证它们不会阻塞)。 |
![]() |
3
29
我担心我在这里“做错事”,如果是这样,请删除我,我道歉。特别是,我没有看到我如何创建一些人创建的整洁的小注释。不过,我对这一问题有许多顾虑/看法。
基本上是假的。如果线程正在计算,那么它不是在摆弄拇指,而是在做必要的工作。另一方面,如果它只是在等待IO的完成,那么它就是 使用CPU时间,内核中线程控制基础设施的全部要点是CPU将找到一些有用的事情来做。这里所建议的“摆弄拇指”的唯一方法是创建一个轮询循环,而编写了真正的web服务器代码的人都不足以做到这一点。 2) “线程是硬的”,只有在数据共享的环境下才有意义。如果你有本质上独立的线程,比如处理独立的web请求时,那么线程就非常简单了,你只需要把如何处理一个作业的线性流编好代码,就知道它将处理多个请求,而且每个请求都是有效独立的。我个人认为,对于大多数程序员来说,学习闭包/回调机制比简单地编写从上到下的线程版本要复杂得多。(但是是的,如果你必须在线程之间通信,生活会变得非常艰难,但是我不相信闭包/回调机制真的改变了这一点,它只是限制了你的选择,因为这种方法仍然可以通过线程实现。不管怎样,这是一个完全不同的讨论,在这里真的不相关)。
4) 到目前为止,我所看到的所有旨在显示Node比其他web服务器快多少的插图都存在严重的缺陷,然而,它们的缺陷确实间接地说明了Node的一个优势,我肯定会接受(而且这绝不是无关紧要的)。节点看起来不需要(实际上甚至不允许)调优。如果有线程模型,则需要创建足够的线程来处理预期的负载。如果做得不好,你的表现就会很差。如果线程太少,那么CPU是空闲的,但是不能接受更多的请求,创建太多的线程,这样会浪费内核内存,在Java环境中,也会浪费主堆内存。现在,对于Java来说,浪费堆是第一个,也是最好的,破坏系统性能的方法,因为高效的垃圾收集(目前,G1可能会改变这一点,但至少在2013年初,这一点还没有定论)取决于有大量的空闲堆。所以,有一个问题,用太少的线程调整它,你有空闲的CPU和低吞吐量,用太多的线程调整它,它在其他方面陷入困境。 内核
a) 关于Node为什么应该更好的一个真正的解释(除了我在上面概述的两个场景之外,我认为第一个场景(糟糕的调优)是到目前为止我看到的所有测试的真正解释。([edit],实际上,我想得越多,我就越想知道大量堆栈使用的内存在这里是否有意义。现代线程的默认堆栈大小往往相当大,但基于闭包的事件系统所分配的内存只是所需的) b) 一个真正的基准测试,它实际上为所选择的线程服务器提供了一个公平的机会。至少这样,我就不得不停止相信这些说法基本上是错误的;([编辑]这可能比我预期的要强烈得多,但我确实觉得对绩效福利给出的解释充其量是不完整的,显示的基准是不合理的)。 干杯, 托比 |
![]() |
4
14
slide 63(internal design) 你看Ryan用 libev (抽象异步事件通知的库)用于非阻塞 eventloop |
![]() |
5
11
线程只用于处理没有异步功能的函数,比如
这个
|
![]() |
6
7
我完全不知道节点.js,但我可以看到使用事件循环如何优于线程化I/O处理。想象一个光盘请求,给我staticFile.x,对那个文件做100个请求。每个请求通常占用一个线程来检索该文件,即100个线程。
一旦单个线程完成,它会将staticFile.x传递给所有100个侦听器并销毁自身,因此下一个请求将创建一个新的线程和发布者对象。 所以在上面的例子中是100个线程对1个线程,但是也是1个磁盘查找而不是100个磁盘查找,增益可能相当可观。瑞安是个聪明人! 从另一个角度来看,这是他在电影开头的一个例子。而不是:
如果一个查询已经在进行中,那么其他相等的查询也会随波逐流,因此在一个数据库往返中可以有100个查询。 |
![]() |
Josue Abotsidia · 创建NextJS项目时出错 6 月前 |
![]() |
Zak · 令牌认证路由的页面刷新重定向到React中的404页面 6 月前 |
![]() |
DSATH · 我的lambda在代码完成之前就结束了,我不知道为什么 6 月前 |