Mutative - 比 Immer 快 10 倍

2023-01-29 10:33:38 +08:00
 unadlib

Mutative - 一个用于高效的 immutable 数据更新的 JavaScript 库,默认情况下比 Immer 快 10 倍,甚至比 reducer 更快。

动机

手写 immutable 数据的更新通常很麻烦且容易出错的。Immer 帮助我们用"突变"逻辑编写更简单的 immutable 更新。

但是它的性能问题导致了运行时的额外性能开销。Immer 默认情况下必须启用自动冻结功能(如果禁用自动冻结功能,性能会变得特别差),这使得 Immer 的 immutable 状态并不够通用。在跨进程、远程数据传输等场景下,我们必须不断冻结这些 immutable 数据。

还有更多可以改进的部分,比如更好的类型推导、非侵入式标记、支持更多类型的 immutability 、更安全的 immutability ,等等。

这就是创建 Mutative 的原因。

Repo: https://github.com/unadlib/mutative

Mutative vs Immer 性能

测量( ops/sec )更新 50K 数组和 1K 对象的性能,越大越好(查看源码). [Mutative v0.3.2 vs Immer v9.0.18]

Naive handcrafted reducer - No Freeze x 3,713 ops/sec ±0.86% (89 runs sampled)
Mutative - No Freeze x 5,323 ops/sec ±1.69% (93 runs sampled)
Immer - No Freeze x 8 ops/sec ±0.88% (23 runs sampled)

Mutative - Freeze x 875 ops/sec ±1.20% (95 runs sampled)
Immer - Freeze x 320 ops/sec ±0.45% (92 runs sampled)

Mutative - Patches and No Freeze x 752 ops/sec ±0.16% (96 runs sampled)
Immer - Patches and No Freeze x 7 ops/sec ±1.32% (23 runs sampled)

Mutative - Patches and Freeze x 425 ops/sec ±0.33% (95 runs sampled)
Immer - Patches and Freeze x 239 ops/sec ±0.99% (89 runs sampled)

The fastest method is Mutative - No Freeze

运行yarn benchmark来在本地重现这些基准测试数据。

OS: macOS 12.6, CPU: Apple M1 Max, Node.js: 16.14.2

Immer 依赖于自动冻结的启用,如果自动冻结被禁用,Immer 将有巨大的性能下降,而 Mutative 将有巨大的性能领先,特别是对于大数据结构,它将有超过 50 倍的性能领先。

因此,如果你使用 Immer ,你将不得不启用自动冻结以提高性能。Mutative 默认允许禁用自动冻结。在两者的默认配置下,我们可以看到 Mutative (5,323 ops/sec)和 Immer (320 ops/sec)之间的明显性能差距。

总的来说,在更多的性能测试场景中,Mutative 比 Immer 有着巨大的性能领先。运行yarn performance可以在本地获得所有的性能测试结果。

特性和优点

Mutative 和 Immer 的区别

- Mutative Immer
Custom shallow copy
Strict mode
No data freeze by default
Non-invasive marking
Complete freeze data
Non-global config
Support IE browser

与 Immer 相比,Mutative 有更少的错误,如意外的草稿逃逸等等,查看详情

Gzip 压缩后的 Mutative 大小为4.16KB。具有相同功能的 Immer 大小为4.67KB

安装

yarn add mutative # npm install mutative

使用

import { create } from "mutative";

const baseState = {
  foo: "bar",
  list: [{ text: "coding" }],
};

const state = create(baseState, (draft) => {
  draft.foo = "foobar";
  draft.list.push({ text: "learning" });
});

create(baseState, (draft) => void, options?: Options): newState

create()的第一个参数是基本状态。Mutative 将其起草并传递给 draft 函数的参数,并执行 draft 突变,直到 draft 函数执行结束,然后 Mutative 将最终定稿状态并产生新的状态。

通过设置选项,使用create()实现更多的高级功能,它也支持 currying 。

FAQs

Mutative 是一个在很大程度上依赖于使用 Proxy 对象的库,Proxy 对象是现代网络浏览器的一个重要功能,允许对对象的各种操作进行拦截。因此,Mutative 可能不完全兼容不支持 Proxy 对象的老式浏览器,如 Internet Explorer 。然而,这些旧的浏览器在整个浏览器市场中只占很小的比例,所以对兼容性的影响可能是最小的。

Mutative 优化的重点是浅拷贝优化、更完整的懒草稿、定稿过程优化等等。

是的。除非你必须与 Internet Explorer 兼容,否则 Mutative 几乎支持 Immer 的所有功能,而且你可以轻松地从 Immer 迁移到 Mutative 。

小结

Mutative 的灵感来自 Immer 。Mutative 的目标是高效的 immutable 更新,专注于性能改进和更好的 API ,带来更好的开发体验。2018 年,Immer 被创建,但到了 2022-2023 年,我们需要一个性能更好的 immutable 更新的库来帮助我们提高应用性能。

1239 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/911243

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX