- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
前段时间我偶然发现了 node.js 并且非常喜欢它。但很快我发现它严重缺乏执行 CPU 密集型任务的能力。所以,我开始使用谷歌搜索并得到了这些解决问题的答案:Fibers、Webworkers 和 Threads (thread-a-gogo)。现在使用哪一个是一个困惑,其中一个肯定需要使用 - 毕竟拥有一个只擅长 IO 而没有别的服务器的目的是什么?需要建议!
更新:
我在想一种方法来晚了;只需要对此提出建议。现在,我想到的是:让我们有一些线程(使用 thread_a_gogo 或 webworkers)。现在,当我们需要更多时,我们可以创造更多。但是在创建过程中会有一些限制。 (不是系统暗示的,但可能是因为开销)。现在,当我们超过限制时,我们可以 fork 一个新 Node ,并开始在它上面创建线程。这样,它可以一直持续到我们达到某个极限(毕竟,进程也有很大的开销)。当达到这个限制时,我们开始排队任务。每当一个线程空闲时,它就会被分配一个新任务。这样,它才能顺利进行。
所以,这就是我的想法。这个主意好不好?我对所有这些过程和线程的东西都有些陌生,所以没有任何专业知识。请分享您的意见。
谢谢。 :)
最佳答案
Node 有一个完全不同的范式,一旦它被正确捕获,就更容易看到这种不同的解决问题的方式。在 Node 应用程序 (1) 中永远不需要多个线程,因为你有不同的方式来做同样的事情。您创建多个进程;但它与例如 Apache Web Server 的 Prefork mpm 的工作方式非常不同。
现在,让我们认为我们只有一个 CPU 内核,我们将开发一个应用程序(以 Node 的方式)来做一些工作。我们的工作是处理一个大文件,它的内容逐字节地运行。对于我们的软件来说,最好的方法是从文件的开头开始工作,逐字节地跟踪到结尾。
-- 嘿,哈桑,我想你要么是我祖父时代的新手,要么是非常老的学校!!!为什么不创建一些线程并使其更快?
-- 哦,我们只有一个 CPU 内核。
——那又怎样?创建一些线程,让它更快!
——它不是那样工作的。如果我创建线程,我会让它变慢。因为我将为系统增加大量开销以在线程之间切换,试图给它们足够的时间,并在我的进程中尝试在这些线程之间进行通信。除了所有这些事实之外,我还必须考虑如何将单个工作分成可以并行完成的多个部分。
——好吧好吧,我看你很穷。让我们用我的电脑吧,它有 32 个内核!
——哇,亲爱的 friend ,你真棒,非常感谢。我很感激!
然后我们回去工作。多亏了这位富有的 friend ,现在我们有了 32 个 cpu 内核。我们必须遵守的规则刚刚改变。现在我们想利用我们所获得的所有这些财富。
要使用多个内核,我们需要找到一种方法将我们的工作分成可以并行处理的部分。如果不是 Node,我们会为此使用线程; 32 个线程,每个 CPU 核心一个。但是,由于我们有 Node,我们将创建 32 个 Node 进程。
线程可以很好地替代 Node 进程,甚至可能是更好的方法;但仅限于特定类型的工作,其中工作已经定义并且我们可以完全控制如何处理它。除此之外,对于工作以我们无法控制且希望尽快回答的方式来自外部的所有其他类型的问题,Node 的方式无疑是优越的。
-- 嘿,Hasan,你还在单线程工作吗?你怎么了,伙计?我刚刚给了你你想要的。你再也没有借口了。创建线程,使其运行得更快。
-- 我已将工作分成几部分,每个流程都将并行处理其中一个部分。
-- 你为什么不创建线程?
-- 抱歉,我认为它不可用。如果你愿意,你可以带上你的电脑吗?
-- 不好吧,我很酷,我只是不明白你为什么不使用线程?
——谢谢你的电脑。 :) 我已经将工作分成几部分,并创建了并行处理这些部分的流程。所有 CPU 内核都将得到充分利用。我可以用线程而不是进程来做到这一点;但是 Node 有这种方式,我的老板 Parth Thakkar 希望我使用 Node。
-- 好的,如果您需要另一台计算机,请告诉我。 :p
如果我创建 33 个进程,而不是 32 个,操作系统的调度程序将暂停一个线程,启动另一个线程,在一些周期后暂停它,再次启动另一个线程......这是不必要的开销。我不想要它。事实上,在具有 32 个内核的系统上,我什至不想创建正好 32 个进程,31 个可能更好。因为不仅仅是我的应用程序可以在这个系统上运行。为其他东西留一点空间可能会很好,特别是如果我们有 32 个房间。
我相信我们现在在充分利用处理器来处理 CPU 密集型任务的问题上是一致的。
-- 嗯,哈桑,对不起,我有点 mock 你。我相信我现在更了解你了。但是我仍然需要解释一些事情:运行数百个线程的所有嗡嗡声是什么?我到处都读到线程的创建速度比 fork 进程快得多?你 fork 进程而不是线程,并且你认为它是你使用 Node 获得的最高值。那么 Node 不适合做这种工作吗?
——别担心,我也很酷。每个人都说这些话,所以我想我已经习惯听到它们了。
——所以? Node 不适合这个?
-- Node 非常适合这个,尽管线程也可以。至于线程/进程创建开销;在你重复很多的事情上,每一毫秒都很重要。但是,我只创建了 32 个进程,而且会花费很少的时间。它只会发生一次。它不会有任何区别。
-- 那我什么时候要创建数千个线程呢?
-- 您永远不想创建数千个线程。但是,在执行来自外部的工作的系统上,例如处理 HTTP 请求的 Web 服务器;如果您为每个请求使用一个线程,您将创建很多线程,其中很多。
-- Node 是不同的,但是?对吗?
——对,没错。这就是 Node 真正闪耀的地方。就像线程比进程轻得多,函数调用也比线程轻得多。 Node 调用函数,而不是创建线程。在 Web 服务器的示例中,每个传入请求都会导致函数调用。
——嗯,有意思;但是如果您不使用多个线程,则只能同时运行一个函数。当大量请求同时到达 Web 服务器时,这如何工作?
-- 您对函数如何运行完全正确,一次一个,而不是两个并行。我的意思是在单个进程中,一次只运行一个范围的代码。 OS 调度程序不会来暂停这个函数并切换到另一个函数,除非它暂停进程以给另一个进程而不是我们进程中的另一个线程留出时间。 (2)
-- 那么一个进程如何一次处理2个请求呢?
-- 只要我们的系统有足够的资源(RAM、网络等),一个进程可以一次处理数以万计的请求。这些功能的运行方式是关键的区别。
——嗯,我现在应该兴奋吗?
-- 也许 :) Node 在队列上运行一个循环。在这个队列中是我们的工作,即我们开始处理传入请求的调用。这里最重要的一点是我们设计函数运行的方式。我们没有开始处理请求并让调用者等待我们完成工作,而是在完成可接受的工作量后迅速结束我们的功能。当我们需要等待另一个组件做一些工作并返回一个值时,我们不再等待,而是简单地完成我们的函数,将其余的工作添加到队列中。
——听起来太复杂了?
-- 不不,我可能听起来很复杂;但系统本身非常简单,而且非常有意义。
现在我想停止引用这两个开发人员之间的对话,并在最后一个关于这些功能如何工作的快速示例之后完成我的回答。
通过这种方式,我们正在做 OS Scheduler 通常会做的事情。我们在某个时候暂停我们的工作,让其他函数调用(如多线程环境中的其他线程)运行,直到再次轮到我们。这比将工作留给操作系统调度程序要好得多,操作系统调度程序试图为系统上的每个线程提供时间。我们比 OS Scheduler 更了解我们正在做的事情,并且我们应该停止时停止。
下面是一个简单的例子,我们打开一个文件并读取它来对数据做一些工作。
同步方式:
Open File
Repeat This:
Read Some
Do the work
Open File and Do this when it is ready: // Our function returns
Repeat this:
Read Some and when it is ready: // Returns again
Do some work
setTimeout(...,0)
来电;有时可能需要在耗时的任务期间暂停,以允许队列中的调用有自己的处理份额。以不同的方式划分任务可以使您免于这些;但是,这并不是真正的黑客,它只是事件队列的工作方式。另外,使用
process.nextTick
自从您使用
setTimeout
以来,这个目标要好得多。 , 计算和检查通过的时间是必要的,而
process.nextTick
就是我们真正想要的:“嘿任务,回到队列的末尾,你已经用完了你的份额!”
关于multithreading - 哪个更适合 node.js 上的并发任务?纤维?网络 worker ?或线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10773564/
我有一个功能是转换 ADO Recordset 进入html: class function RecordsetToHtml(const rs: _Recordset): WideString; 该函
经过几天的研究和讨论,我想出了这种方法来收集访客的熵(你可以看到我的研究历史here) 当用户访问时,我运行此代码: $entropy=sha1(microtime().$pepper.$_SERVE
给定一个无序列表 List ,我需要查找是否存在 String与提供的字符串匹配。 所以,我循环 for (String k : keys) { if (Utils.keysM
我已经搜索过这个问题,但没有找到我正在寻找的答案。 基本上,我想将类构造函数包装在 try/except 子句中,以便它忽略构造函数内特定类型的错误(但无论如何都会记录并打印它们)。我发现做到这一点的
我有一组三个数字,我想将一组数字与另一组数字进行比较。即,第一组中的每个数字小于另一组中的至少一个数字。需要注意的是,第一组中的下一个数字必须小于第二组中的不同数字(即,{6,1,6} 对 {8,8,
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
首先介绍一下背景: 我正在开发一个带有 EJB 模块和应用程序客户端模块的企业应用程序 (ear)。我还使用 hibernate JPA 来实现持久性,并使用 swingx 来实现 GUI。这些是唯一
我正在尝试在我的上网本上运行 Eclipse 以便能够为 Android 进行开发。 您可能已经猜到了,Eclipse 非常慢,并且不容易有效地开发。 我正在使用 Linux Ubuntu 并且我还有
for row, instrument in enumerate(instruments): for col, value in enumerate(instrument):
return not a and not b ^ 我如何以更好的格式表达它 最佳答案 DeMorgan's Law , 也许? return not (a or b) 我认为在这一点上已经足够简单了
我正在尝试让 Font Awesome 图标看起来更 slim https://jsfiddle.net/cliffeee/7L6ehw9r/1/ . 我尝试使用“-webkit-text-strok
假设我有一个名为 vals 的数据框,如下所示: id…………日期…………min_date…… .........最大日期 1…………2016/01/01…………2017/01/01…………2018/
是否有更 Pythonic 的方式来做到这一点?: if self.name2info[name]['prereqs'] is None: se
我有一个函数可以将一些文本打印到它接收到的 ostream&。如果 ostream 以终端为目标,我想让它适应终端宽度,否则默认为某个值。 我现在做的是: 从 ostream 中获取一个 ofstre
这个问题在这里已经有了答案: Should a retrieval method return 'null' or throw an exception when it can't produce
我有这个 bc = 'off' if c.page == 'blog': bc = 'on' print(bc) 有没有更 Pythonic(和/或更短)的方式在 Python 中编写? 最佳
输入:一个包含 50,000 行的 CSV;每行包含 910 列值 0/1。 输出:运行我的 CNN 的数据框。 我编写了一个逐行读取 CSV 的代码。对于每一行,我将数据分成两部分,称为神经元(90
据我所知,with block 会在您退出 block 后自动调用 close(),并且它通常用于确保不会忘记关闭一个文件。 好像没有技术上的区别 with open(file, 'r+') as f
我有一个使用 Entity Framework V6.1.1 的 MVC 5 网站。 Entity Framework DbContext 类和模型最初都在网站项目中。这个项目有 3 个 DbCont
我是编程新手,在尝试通过将 tableView 和关联 View 的创建移动到单独的类并将委托(delegate)和数据源从 VC 移动到单独的类来精简我的 ViewController 时遇到了一些
我是一名优秀的程序员,十分优秀!