草庐IT

javascript - 在 Node 中的进程之间发送数据是否昂贵/高效?

coder 2024-07-16 原文

Node 允许您生成子进程并在它们之间发送数据。例如,您可以使用它来执行一些阻塞代码。

文档说“这些子 Node 仍然是 V8 的全新实例。假设每个新 Node 至少需要 30 毫秒的启动时间和 10mb 的内存。也就是说,您不能创建数千个子 Node 。”

我想知道它是否有效,我是否应该担心一些限制?这是示例代码:

//index.js
var childProcess1 = childProcess.fork('./child1.js');

childProcess1.send(largeArray);

childProcess1.once('message', function(formattedData) {
  console.log(formattedData);
  return false;
});



//child1.js
process.on('message', function(data) {

  data = format(data); //do smth with data, then send it back to index.js

  try{
    process.send(data);
    return false;
  }
  catch(err){
    console.log(err);
    return false;
  }

});

最佳答案

文档告诉您启动新的 Node 进程是(相对)昂贵的。每次需要工作时都 fork() 是不明智的。

相反,您应该维护一个长期运行的工作进程池——就像线程池一样。在您的主进程中排队工作请求,并在空闲时将它们分派(dispatch)给下一个可用的工作人员。

这给我们留下了一个关于 Node IPC 机制的性能概况的问题。当您fork() 时,node 会自动在子进程上设置一个特殊的文件描述符。它使用它通过读取和写入以行分隔的 JSON 在进程之间进行通信。基本上,当您 process.send({ ... }) 时, Node JSON.stringify 将其写入序列化字符串并将其写入 fd。接收进程读取此数据,直到遇到换行符,然后 JSON.parses 它。

这必然意味着性能将在很大程度上取决于您在进程之间发送的数据的大小。

我已经粗略地进行了一些测试,以更好地了解这种性能。

首先,我向 worker 发送了 N 字节的消息,worker 立即以相同长度的消息响应。我在我的四核超线程 i7 上尝试了 1 到 8 个并发工作器。

我们可以看到,拥有至少 2 个 worker 对原始吞吐量有利,但超过 2 个基本上无关紧要。

接下来,我向 worker 发送了一条空消息,worker 立即回复了一条 N 字节的消息。

令人惊讶的是,这没有任何区别。

最后,我尝试向 worker 发送 N 字节的消息,它立即返回一条空消息。

有趣 — 性能不会随着消息的增大而迅速下降。

要点

  • 接收大消息比发送它们稍微贵一些。为了获得最佳吞吐量,您的主进程不应发送大于 1 kB 的消息,并且不应接收大于 128 字节的消息。

  • 对于小消息,IPC 开销约为 0.02 毫秒。这个小到足以在现实世界中无关紧要。

重要的是要认识到消息的序列化是一个同步的、阻塞的调用;如果开销太大,你的整个 Node 进程将在发送消息时被卡住。这意味着 I/O 将被饿死,您将无法处理任何其他事件(如传入的 HTTP 请求)。那么可以通过 Node IPC 发送的最大数据量是多少?

超过 32 kB 时事情变得非常糟糕。 (这些是每条消息;双倍以获得往返开销。)

这个故事的寓意是你应该:

  • 如果输入大于 32 kB,想办法让您的工作人员获取实际数据集。如果您要从数据库或其他网络位置提取数据,请在 worker 中执行请求。不要让 master 获取数据,然后尝试在消息中发送它。该消息应该只包含足以让工作人员完成其工作的信息。将消息视为函数参数。

  • 如果输出大于 32 kB,想办法让工作人员在消息之外传递结果。写入磁盘或 send the socket to the worker以便您可以直接从工作进程响应。

关于javascript - 在 Node 中的进程之间发送数据是否昂贵/高效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27321392/

有关javascript - 在 Node 中的进程之间发送数据是否昂贵/高效?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  7. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  10. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

随机推荐