Mobx表现

Mac*_*Mac 8 javascript performance mobx

我从不同的资料中读到,mobx优于反应渲染器,并且比redux更快.但是,如果我做了几个测试,它表明向mobx observables添加新数据非常慢.在反应原生环境中每毫秒都很重要并且使用解决方案很困难,即使循环超过200个元素和填充数组需要超过100毫秒因为我真的很喜欢mobx我希望有人可以看看测试代码并给我一些提示 - 我是什么我做错了,如何提高绩效.

import {observable, transaction,autorun} from 'mobx'; 
class Runner {

list = observable([]);

run() {


    const start = new Date().getTime();
    transaction(() => {
        for (let i = 0; i < 200; i++) {
            this.list.push({
                id: observable(i),
                one: observable('1'),
                two: '2',
                three: 3,
                x: 'xxxxx',
                y: 'yyyyy',
                z: 'zzzzz',
                z1: 'zzzzz',
                z2: 'zzzzz',
                z3: 'zzzzz',
                z4: 'zzzzz',

            });
        }
    });

    console.log('Execution time: ' + (new Date().getTime() - start) + 'ms services ');
}
}
const runner = new Runner();
autorun(() => console.log(runner.list));
runner.run();
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑上,它需要大约120毫秒才能完成.没有可观察的时间,它需要不到1毫秒

mwe*_*ate 26

你没有做任何根本错误的事情(除了,正如罗伯特已经指出的那样,目前所有的属性都是可观察的,因为默认情况下可观察的是普通数据结构的recurses).

主要的是你还没有真正使用MobX :)你的测试结果是正确的,可观察的数据结构比普通结构贵得多.这有点比较苹果和橘子.或者为了更好的类比; 这就像基准化连接字符串以生成HTML而不是使用DOM来生成HTML.弦乐将永远胜利.

然而,在完整应用程序的大局中,情况有所不同.假设您需要更改元素的边框颜色.然后DOM可能会突然变得更有效率,因为它允许您只改变HTML的一个非常特定的部分,并且DOM足够聪明以确定需要在屏幕上重新绘制哪些像素.如果你只是一个简单的字符串,那将会更加困难.

MobX类似,不是从快速数据结构中获得它的性能,而是从它们的智能性.如果修改了一个可观察数组,MobX会精确查明哪些操作需要呈现哪些组件与您编写的任何计算一致.因为MobX能够建立更细粒度的"事件监听器",所以当你手工编写这类东西时你会这么做,而且因为MobX可以优化依赖树,人类程序员可能不会这么做,MobX可以非常快速.但是你必须从整个国家整个生命周期的大局看到它.如果你只是想非常快地创建一些对象和数组,那么没有什么能胜过普通数组和构造函数.

我建议您阅读@lavrton的这篇博客https://medium.com/@lavrton/how-to-optimise-rendering-of-a-set-of-elements-in-react-ad01f5b161ae#.enlk3n68g.它很好地演示了手动优化时跳槽所需的所有箍,只是为了接近MobX可以更新组件的速度.

我希望这能解释你的结果!

PS目前有一些已知的情况,在分类或清理大型集合时,MobX可能会很慢.这些将在即将发布的2.4.0版本中解决.

  • Michel,我的目标不是对 MobX 进行基准测试,我发现在真正的 React-Native + MobX 应用程序(在模拟器上)上,屏幕上显示 5 个条目的速度很慢,这就是我进行这个愚蠢测试的原因。在设备上,具有 5 个条目的完全相同的循环花费了更多时间 - 大约 40 毫秒。由于react-native在同一个javascript线程上做所有事情,那么在错误的地方花费40毫秒将会很明显,我没有意识到的一件事是MobX做了更多的事情。MobX 也渲染东西。因此,如果我测量了 40 毫秒的“循环时间”,那么它实际上意味着循环条目 + 渲染屏幕上的所有内容:) (2认同)

rob*_*lep 10

observable() 使你在数组中推送的所有值(递归地)都是可观察的,这可能不是你需要的.

例如,从您的示例代码可以看出,您只想观察ida属性的更改,而不是其余的.在这种情况下,您可以在可观察数组上使用asFlat修饰符:

const { observable, autorun, transaction, asFlat } = mobx;
....
list = observable(asFlat([]));
Run Code Online (Sandbox Code Playgroud)

这将允许您观察到的变化list本身(新项目增加,项目中去除,等等),或在ida列表项的属性,而不是休息.

这对我来说大大加快了测试速度:从35ms到大约5ms.


sea*_*lea 0

如果您在交易之外构建所有新项目,性能如何?

const start = new Date().getTime();
const newItems = [];
for (let i = 0; i < 200; i++) {
    newItems.push({
        id: observable(i),
        one: observable('1'),
        two: '2',
        three: 3,
        x: 'xxxxx',
        y: 'yyyyy',
        z: 'zzzzz',
        z1: 'zzzzz',
        z2: 'zzzzz',
        z3: 'zzzzz',
        z4: 'zzzzz',

    });
}
transaction(() => {
    Array.prototype.push.apply(this.items, newItems)
});
Run Code Online (Sandbox Code Playgroud)

然后尝试不使用observablearoundidone,然后尝试不使用事务(因为现在对...的所有更改都this.items在一次调用中完成Array.prototype.push