【问题标题】:Is there a performance penalty for using pure functions with heavy arguments?使用带有大量参数的纯函数是否会降低性能?
【发布时间】:2021-05-13 09:35:21
【问题描述】:

我真的很喜欢纯函数方法,原因有很多,但我的主要观点是,如果它有相当大的性能损失,特别是在大量争论的情况下。

例如,而不是这个:

// no pure function
import bigState from './somewhere' // imagine a whole state with lots of values.

const impure = () => {
  // do something with bigState
}

// pure function
const pure = (bigState) => {
  // do something with bigState
}

使用这种函数和参数做大量工作的应用会受到惩罚吗?

【问题讨论】:

  • 如果你将一个对象传递给一个函数,那就是引用,所以严格来说,一旦对象被修改,它就不再是纯粹的了。
  • 这有什么关系?您认为大型对象引用会更慢吗?您不会像携带一个装满东西的大盒子那样传递物体。您正在传递参考。这就像你想在一家大卖场买一件大件的东西,你抓起一张纸,拿着它走到前面。你不是在商店里拖着那个巨大的物品。
  • 对象不像字符串。如果是,它将是不可变的。
  • “激烈争论”到底是什么意思?其中很多?还是只是对具有许多属性的巨大对象的引用?

标签: javascript typescript performance functional-programming arguments


【解决方案1】:

如果你想使用纯函数,你必须传入一个你不能修改的只读对象。要修改状态,您的纯函数必须返回经过修改的状态副本,而不是更新原始状态。

就传递参数而言,您的状态大小并不真正相关。您传入对大状态对象的(小)引用,而不是实际对象本身。无论你的状态有多大,参数的大小都是一样的。

如果你有一个非常大的状态,那么使用严格的纯函数将导致每次修改时复制大量状态。

要解决这个问题,您可以考虑使用状态管理工具(例如 immutable.js 或 redux)来代表您提供性能优化。

更新

我应该补充一点,纯函数的重要之处不在于它如何从调用环境中获取输入,而在于它如何处理该输入。如果一个函数有副作用,那么它就不是纯函数,不管它是使用引用参数还是全局变量来引起副作用。

在函数式语言(例如 Haskell)中,编译器将帮助您防止创建不纯函数。 javascript等语言没有直接的函数式编程支持,你必须通过自己编写函数式代码来确保可重复性并避免副作用。

在 javascript/typescript 中帮助强制执行此操作的最简单方法之一是使用不可变状态*。如果您的状态是不可变的,那么在函数执行期间您更难意外更改它。它还有助于在传递参考变量时确保可重复的结果。如果被引用的对象是不可变的,那么如果对同一对象的引用再次传递给函数,则可以依赖该函数来提供一致的结果。

*当然 - javascript 中很少有实际上是只读的。如果开发人员足够努力,总有办法颠覆您的只读意图。

【讨论】:

  • 嗨,我猜你的意思是 immutable.js
  • @geoffrey - 谢谢,是的,我的意思是 immutable.js。 Immutify 是我们对图书馆的私人昵称,我搞混了。
【解决方案2】:

我想补充一点,因为不变性使事情变得如此可预测,所以不可变的数据结构可以共享

最简单的例子是单链表:

const c = {head: "c", tail: null};
const bc = {head: "b", tail: c};
const abc = {head: "a", tail: bc};

// zbc and abc share bc
const zbc = {head: "z", tail: bc};

const join = ({head, tail}) =>
  tail == null
  ? head
  : head + join(tail)
;

join(abc) // "abc"
join(zbc) // "zbc"

如果您按照建议使用不可变数据结构,它们将具有结构共享。

当您来自命令式世界时,对不可变性的自然解释是,您必须先对事物进行深层复制,然后才能安全地用突变接触它们,但反过来:因为没有突变,您不需要深拷贝。

【讨论】:

    猜你喜欢
    • 2022-10-07
    • 1970-01-01
    • 2019-08-09
    • 2017-08-18
    • 2023-03-22
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多