Vue: Low performance at adding new element to list

Created on 25 Sep 2017  ·  8Comments  ·  Source: vuejs/vue

Version

2.4.4

Reproduction link

https://jsfiddle.net/go14z0yh/1/

Steps to reproduce

  1. Open link
  2. Start recording performance (chrome developer tools -> performance)
  3. Click on the button
  4. Stop recording

What is expected?

It is expected that adding 1 message does not require heavy calculations (less then 1ms).

What is actually happening?

In practice, it turns out that the list is completely rendered again (in a virtual DOM). These calculations take about 30ms (core i7 4770k).


I think this point can obviously be optimized.

Most helpful comment

these calculations take about 30ms

I think it's pretty decent score for such a large array :) Out of curiosity i checked how React is doing in such a case and it takes around 130-160 ms to render this size of an array on my pc (i5-4690k). Vue as you said ~30 ms

All 8 comments

This is expected behavior. VDOM by definition needs to generate 10,000 virtual elements and iterate through them to find diffs. If you have an "obvious" way to optimize them, please submit a PR.

Why can not you add a wrapper for example for Array.push, Array.filter and so on? To make it possible to do the computed properties on their basis and vue understood which elements of the array have changed.

these calculations take about 30ms

I think it's pretty decent score for such a large array :) Out of curiosity i checked how React is doing in such a case and it takes around 130-160 ms to render this size of an array on my pc (i5-4690k). Vue as you said ~30 ms

In native JS this action takes 0.68 ms (with the exception of the 'layout' and 'update layer tree'), in vue 30-60 ms. A huge difference. I'm sure that you can make it possible to tell vue which particular part of the array has changed. https://jsfiddle.net/go14z0yh/2/

Modifying the DOM manually will always be faster, because you skip all the data update, virtual DOM diffing parts. The thing is you can't realistically write all the DOM manipulations directly when building a medium to big app because it will become too complex and you will eventually end up with buggy/un-maintenable code. Vue abstracts the DOM away from you so you don't need to think about it, but by definition abstractions have a cost.

I understand this, but I still think it should be possible to prompt vue on what changes in the data you need to pay attention to, and which ones do not. I do not propose to get rid of VDOM, I just want it to be possible to more flexibly organize the rendering. If I could tell vue.js that I just added 1 element to the array, and did not change it all, then vue could take the previous version of VDOM and just add one element to it, not rerendering all the rest. It's the same with synchronizing VDOM and DOM. In this case, vue would know that all the other elements have not changed and it would have just added one new. I think this is quite feasible and would greatly enhance the rendering performance.

I'm not sure it could be applied in this case, but dividing into multiple components is a way to cache parts of the VDOM.

Adding one item to the array does not always means adding one element to the DOMList, it may be more complicated.
What if your template looks like:

<div id="app">
  <button @click="add" v-if="messages.length < 10002">
    Add 1 message
  </button>
  <p v-for="(message, index) in messages" :key="message" v-if="!(messages.length > 10000 && index === 9999)">{{ message }}</p>
</div>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

wenLiangcan picture wenLiangcan  ·  39Comments

yyx990803 picture yyx990803  ·  210Comments

okjesse picture okjesse  ·  49Comments

karevn picture karevn  ·  42Comments

asiFarran picture asiFarran  ·  34Comments