Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

node 的硬伤:coroutine

  我一直以来都觉得 JavaScript 挺好的,就算是各种回调也不觉得有啥问题。Promise 已经可以让代码不再嵌套得跟屎一样。将来还会有 async/await 可以让异步以同步的方式写,显得更加优雅。而且即便是现在,call/cc 的概念也已经通过 generator/yield 被引入到 JavaScript 中了。   可是这一切并没有解决 coroutine 的问题,无论是 generator/yield 还是 async/await,都只是 semi-coroutine 而已。就拿 async/await 为例,如果一个函数要用到 await,那它就必须是 async 的。如果一个顶层函数需要 await,那么可能整个程序的调用链都得是 async 的。而 async 的函数被调用时都在一个新的 coroutine 中,这就造成了大量 coroutine 切换的性能开销。
  其实这里拿 async/await 举例有点不太恰当,因为 async/await 本身是基于 Promise 的,它还有一个异步的过程,除了上面的 coroutine 切换问题外还有调用堆栈的释放问题。因为 Promise 的异步会造成每次执行都重置调用堆栈,这也是一个不小的性能开销。上面的例子其实用 generator/yield 来举例会更合适。
  也许在写业务代码时,无论用 async/await 还是 generator/yield 都没什么性能问题,因为异步的业务瓶颈都不在这里。可是如果用 node 写一个底层框架就要考虑这些问题了。比如做协议解析时我们需要频繁地从字节流中读取很小的数据,如果每次读几个字节都做一次 coroutine 切换的话,遇到稍大的数据就能直接感受到性能问题。正确的做法应该是在 buffer 还有数据时同步读,之后当 buffer 空了之后才去切换 coroutine。可是这是 node 做不到的,或者说,node 对这种场景使用了回调的方案。
  对于 coroutine 的处理方面应该算是 node 的硬伤了,虽然通过 C++ 插件可以把一些高性能需求的东西封装起来可以解决业务上的问题,但实际上这是在绕过问题,并没有解决 node 本身的问题。
网名:
54.161.77.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^