【问题标题】:When is delay too large for choosing synchronous calculation in NodeJS?什么时候延迟太大而无法在 NodeJS 中选择同步计算?
【发布时间】:2017-10-14 07:18:08
【问题描述】:

我正在编写一个 node.js 插件来执行一些加密计算,这可能需要大约 1 μs - 20 μs。现在我有一个选择:将其实现为同步方法还是异步方法(在后台工作人员上进行计算)?

很明显,网络和 I/O(有时需要超过一毫秒)应该异步完成。解析 JSON 输入很快,应该同步完成。

在我的情况下,保持低延迟很重要,但优化微秒感觉很像过早的优化。因此,考虑到这种情况,我很想了解您对这个问题的看法:

使用 node.js 时,(同步)调用必须阻塞多长时间,直到您决定在后台线程上异步运行它?

【问题讨论】:

  • 为什么在单线程环境中任何东西都应该是同步的?没有理由 imo

标签: javascript node.js latency


【解决方案1】:

很明显,网络和 I/O(有时需要超过一毫秒)应该异步完成。解析 JSON 输入很快,应该同步完成。

这不是很明显。 Node 有异步 JSON 解析器。见:

但确实在某些时候,对于 CPU 密集型操作,您需要使用异步操作。我想说任何 CPU 密集型逻辑不应该在阻塞事件循环的主线程中完成,而应该在外部进程或工作线程中完成,或者在从 C++ 产生的线程中完成以最大限度地发挥作用对用户透明。

bcryptbcrypt-nodejs 中查看它是如何完成的:

如果您可以使您的函数异步工作(不仅在使用回调的意义上,而且实际上不阻塞事件循环),那么我建议您至少制作两种 API - 一个接受回调的函数和一个函数返回一个承诺(在实践中可以是一个函数)。

目前使用 async/await,您可以使用任何返回 promise 的函数,几乎就像它是同步的一样:

let x = await f();
let y = await g(x);
// ...

但在某些情况下,您需要一个真正的同步函数,例如,如果您想拥有可以直接从模块中导出的东西:

module.exports = f();

这里当f() 函数被阻塞时并没有什么坏处,因为require() 本身也被阻塞了,你应该只在启动时使用它一次。但是如果函数是异步的——通过使用async 关键字声明并隐式返回一个promise,通过显式返回一个promise 或通过回调,那么您将无法从模块中导出值并使用它在某些方面。

因此,如果您认为函数的返回值可以从模块中导出是有意义的,那么您可能还需要提供一个阻塞的同步版本。

【讨论】:

    【解决方案2】:

    为什么不将其实现为同步 AND 作为具有两个函数的异步方法,例如 cryptAsync()cryptSync() ?我觉得你这样做比较好,也不难。

    【讨论】:

    • 作为 API 设计师,我希望为用户做出这个选择。如果其中一个功能似乎是更好的选择,我想省略另一个(以使 API 尽可能简单)。
    • 那我觉得异步比较好
    猜你喜欢
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-27
    • 2017-04-15
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多