【问题标题】:Best Practice for Callback Parameters in NodeJsNodeJs 中回调参数的最佳实践
【发布时间】:2020-04-04 17:04:05
【问题描述】:

背景

我是 Node.js 中 fast object traversal 的低级库的维护者。该库的重点是速度,并且经过大量优化。但是有一个很大的放缓:回调参数

问题

回调由库使用者提供,每次扫描可以多次调用。对于每次调用,都会计算所有参数并将其传递给回调。在大多数情况下,回调实际上只使用了一小部分参数。

目标

目标是消除这些参数的不必要计算。

解决方案思路

  • 理想情况下,NodeJs 会公开回调定义的回调参数。然而,如果没有大量的黑魔法(字符串解析),似乎不可能获得它们。它也无法解决仅有条件地需要参数的情况。
  • 我们可以要求回调公开所需的参数,而不是尝试从回调中获取参数。这听起来很不方便且容易出错,而且也无法解决有条件的需求。
  • 我们可以为每个参数组合引入不同的回调。这听起来是个坏主意。
  • 我们可以为每个参数传入一个计算并返回参数值的函数,而不是直接传入参数。在回调内部,参数将根据需要被调用。这很丑陋,但可能是最好的方法?

问题

  • 其他库如何解决这个问题?
  • 还有什么其他方法可以解决这个问题?

这是一个非常基本的设计决策,我正在努力做到这一点。

非常感谢您的宝贵时间!一如既往的感激!

【问题讨论】:

  • 据我所知,你的回调只有三个参数?
  • @Bergi 不幸的是没有。第三个参数是一个对象,里面隐藏了很多参数。

标签: javascript node.js optimization callback software-design


【解决方案1】:

您可以向回调传递一个对象,该对象上有各种方法,使用回调的客户端可以调用该对象以获取他们实际需要的任何参数。这样,您将拥有一个干净的对象接口,并且您只需计算实际请求的必要信息。

这种通用设计模式有时被称为“惰性计算”,您只需根据需要进行计算。您可以使用访问器函数或 getter,具体取决于您要公开的接口类型。

出于性能原因,您或许可以在每次调用回调时重用同一个对象,而不是构建一个新对象(取决于您的实现细节)。

请注意,您甚至不必将计算所需的所有信息都放入对象本身,因为在某些情况下,对象上的方法可以在进行计算时引用您自己的本地上下文和本地范围的变量.

【讨论】:

  • 这是很棒的输入!谢谢你。稍后会接受,除非弹出更好的答案
  • 此更改的 PR 目前正在此处等待处理:github.com/blackflux/object-scan/pull/971 再次感谢您的意见!这正是我想要的
【解决方案2】:

但是有一个很大的减速:回调参数

您真的对此进行了基准测试吗?我怀疑构建参数值是否昂贵。请注意,如果这是一个非常频繁使用的调用,V8 可能能够内联它,然后优化掉未使用的参数值。

理想情况下,NodeJs 会公开回调定义的回调参数。

其实it does。但是,如果您确实想依赖此属性,则应正确记录您所做的,否则这种魔法可能会导致难以理解的错误。

我们可以为每个参数组合引入不同的回调。这听起来是个坏主意。

提供filter(key, value)filterDetailed(key, value, context) 这两个选项似乎不是什么大问题。如果优化真的值得,而且正如你所说,这是一个低级库,那就去吧。

我们可以为每个参数传入一个计算并返回参数值的函数,而不是直接传递参数。在回调内部,参数将根据需要被调用。这很丑陋,但可能是最好的方法?

构造一个要传递的闭包对象而不是参数确实也有一些开销,因此您需要正确地进行基准测试。这可能不值得。

但是,我看到您实际上传递了一个上下文对象作为参数,计算值作为属性被访问。在这种情况下,您可以简单地使这些属性 getter 在访问它们时计算值,而不是在构造对象时计算值。

【讨论】:

  • (1) 是的,我做到了!编译和注入使这大约慢 4-8 倍。 V8 很聪明,但不幸的是没有那么聪明。 (2) 可以访问许多不同的参数,例如当第二个参数需要时,第一个参数并不总是需要。因此,忽略该 function.length 具有奇怪的行为(正如您所提到的),这不适用于这种情况(3)不幸的是,上下文“隐藏”了更多参数。所以会有很多 cb 组合 (4) 我现在正在考虑为所有调用保留一个闭包对象,正如@jfriend00 提到的那样。这将消除开销
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多