【问题标题】:Node.js stream write in loopNode.js 流循环写入
【发布时间】:2014-11-05 19:31:59
【问题描述】:

我最近尝试对一些 node.js 原生功能进行基准测试,结果发现了一些我无法理解的令人毛骨悚然的结果。下面是一个简单的代码,我进行了基准测试和基准测试结果:

http://pastebin.com/0eeBGSV9

您可以看到,它在 200 个并发的情况下每秒处理 100k 个请求的健康请求数为 8553 个。然后我被一个朋友指示,在这种情况下我不应该使用异步,因为这个循环不足以阻止节点的事件循环,所以我重构了代码以使用 for 循环,它甚至增加了基准测试结果更高:

http://pastebin.com/0jgRPNEC

这里我们每秒有 9174 个请求。整洁的。 (奇怪的是,即使我将迭代次数更改为 10k,for 循环版本也始终比异步版本快)。

但是后来我的朋友徘徊,如果这个结果可以通过使用流而不是在循环完成后转储所有数据来进一步推动。我再次重构代码以使用 res.write 来处理数据输出:

http://pastebin.com/wM0x5nh9

aaaa 我们每秒有 2860 个请求。 这里发生了什么?为什么流式写入如此缓慢?我的代码中是否存在某种错误,或者这是否是节点实际处理流的方式?

ubuntu 上的节点版本是 0.10.25,默认设置来自 apt 安装。

我还在开始时针对 JXCore 和 HHVM(使用节点代码的 async.js 版本)测试了相同的代码,结果如下:http://pastebin.com/6tuYGhYG 并得到一个奇怪的结果,即节点集群比最新的 jxcore 2.3.2 更快。

任何批评都将不胜感激。

编辑:@Mscdex,我很好奇调用 res.write() 是否可能是问题,所以我改变了将数据推送到新流以供 res 使用的方式。我天真地相信,也许这种方式节点会以某种有效的方式优化输出缓冲和流数据。虽然这个解决方案也有效,但它比以前更慢:

http://pastebin.com/erF6YKS5

【问题讨论】:

  • 仅供参考,使用异步不会自动使您的代码异步。您的第一个基准测试比简单的 for 循环慢,因为它本质上只是一个简单的 for 循环,增加了异步库的开销。
  • 是的,我在基准测试之后意识到了这一点。然而,这并不能解释为什么流媒体很糟糕。刚刚通过排水事件进行了背压检测测试,它仍然在 2900 rps 左右。

标签: javascript node.js benchmarking hhvm jxcore


【解决方案1】:

我的猜测是有许多单独的 write() 系统调用所涉及的开销。

在节点 v0.12+ 中,“软木塞”功能 has been added 以便您可以随心所欲地执行 res.write(),但您可以对流进行软木塞和解塞,这样所有这些写入只会产生一个write() 系统调用。这本质上就是您现在通过连接输出所做的事情,除了软木塞会为您做这件事。在 node core 的某些地方,这个 corking 功能也可以在后台自动使用,这样您就不必显式地 cork/uncork 以获得良好的性能。

【讨论】:

  • 我想使用流是有原因的——它是流。我不想要一个 write() 系统调用,它不是流式传输,而是将整个输出一次性发送。我希望节点在从 for 循环中获取输出时对其进行流式传输,而不是对其进行缓冲(因为我可以简单地将所有内容连接到一个变量中,然后使用 res.end())并推送到客户端。
猜你喜欢
  • 2023-03-20
  • 2021-09-15
  • 2012-08-08
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 2017-04-08
  • 2014-03-13
  • 1970-01-01
相关资源
最近更新 更多