4

In terms of performance, is it better to have 20 elements (with their children) in the DOM tree or everything stored in a Javascript object?

Case 1:

<html>
    <body>
        <div id='el1'>
            <span>...</span>
            ...
        </div>
        <div id='el2'>            
            <p>...</p>
            ...
        </div>
        <div id='el3'>            
            <img src="" alt="" />
            <br/>
        </div>
        <div id='el4'>
            <section></section>
            ...
        </div>
        ...
    </body>
</html>

Case 2:

var OBJ = {};
OBJ.el1 = $("<div id='el1'><span>...</span>...</div>");
OBJ.el2 = $("<div id='el1'><p>...</p>...</div>");
OBJ.el3 = $("<div id='el1'><img src="" alt="" /><br/>...</div>");
OBJ.el4 = $("<div id='el1'><section></section>...</div>");
....

My application should only show one of these elements at once. Will it perform better if I just leave them in DOM tree and change their style, or is it preferably to store them in a Javascript object and remove and append them when needed?

How could I test it?

@edit Extra info to consider:

1- all elements were written in the HTML document and then removed and stored in javascript objects when page was loaded.

2- Everytime the active element changes, I have change the DOM structure by removing the current active element and then appending the new one to it.

@EDIT 2: after some tests

The idea is: someone will write the HTML elements to DOM and then Javascript must show/hide only one of these elements at once. These elements have their own children. It may be a Full Page website or a Web App.

I created 2 test cases:

1- Elements will be removed and then re-appended several times by Javascript. So they will be stored in a Javascript object until it's summoned

2- Elements will be in DOM, I'll hide and show them (jQuery functions, but further tests will change the CSS directly) when needed.

<html>
<head>
    <script src='https://code.jquery.com/jquery-1.11.3.min.js'></script>
</head>
<body>
    <!-- I USED 15 ELEMENTS IN MY TEST, BUT THE CODE IS TOO LONG -->
    <script>
    var OBJ1 = {};
    var OBJ2 = new Array();
    var ACTIVE;
    var BODY = $(document.body);
    var T1, T2, DELTA;

    $(function(){
        T1 = new Date().getTime();
        /*
        //TEST 1: Javascript
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ1[id] = _this;
            _this.remove();
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k in OBJ1){
                c = OBJ1[k];
                if(ACTIVE) ACTIVE.remove();
                BODY.append(c);
                ACTIVE = c;
            }
        }*/

        //TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.hide();
                c.show();
                ACTIVE = c;
            }
        }

        T2 = new Date().getTime();
        DELTA = T2 - T1;
        console.log('It took '+DELTA+' milliseconds');
    });
    </script>        
</body>

I created 5 generic elements with some Lorem Ipsum and Lorem Pixel content and them copied/pasted them 3 times, making 15 1st-level elements.

For 1000 times I hide and revealed each one of the 15 elements. Ran the test 3 times each.

Case 1 (winner so far): 5.2s, 4.75s, 4.85s

Case 2: 21.5s, 21.5s, 20s

@edit 3: changing Case 2 method

Changing the second case from hide()/show() to css() makes a high increase in performance.

//TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            _this.css('display','none');
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 15000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.css('display','none');
                c.css('display','block');
                ACTIVE = c;
            }
        }

Also increase the loop to 15k.

Case 1: Around 6.5s

Case 2: Around 2.5s

3
  • For only four elements, it doesn't matter. When you get into the thousands you may see a discernable difference. Measure it to be sure. There are other things to consider here, too. For example, one of your elements contains img and so you may want to consider whether you want to preload the image resource. If you inject the img into the DOM with script then it won't start loading until that the element is added to DOM. Commented Oct 10, 2015 at 15:58
  • 1
    Interesting results. I also found css('display') to be much faster than show()/hide(). Here is a perf test I was playing with; it's a simpler case than yours but still emphasizes that the show/hide with css() works better in this case than removing and appending. See jsperf: jsperf.com/dynamic-dom-performance Commented Oct 11, 2015 at 5:31
  • 1
    Seeing consistent results in Chrome, Firefox, IE, and Edge. (funny; browserscope detects Edge as Chrome 42) Commented Oct 11, 2015 at 5:43

3 Answers 3

5

Definitely leave it in the DOM tree. I would just use show/hide methods to show which one you want.

I would only use the JS method if there was a dynamic changing value that should be reflected in the element, but if they are all static, changing the DOM tree is much more performance heavy rather than just a CSS style change.

You can test this by writing both, then using a jsperf to compare.

Sign up to request clarification or add additional context in comments.

Comments

0

Javascript is a very fast language, however the DOM is a huge bottleneck. So having the data in a Javascript object will be much faster, but you will have to render the active element to the DOM on your own (Instead of just making it visible).

I wouldn't worry about the DOM being slow for a few dozen elements, but if you have lots of elements or are trying to perform computations/filters on them, definitely go for Javascript.

4 Comments

"but you will have to render the active element to the DOM on your own (Instead of just making it visible)." What do you mean with it? You mean removing the previously active element and then appending the newly active one?
Do you still think Javascript is faster even considering: 1- all elements were written in the HTML document and then removed and stored in javascript objects when page was loaded. 2- Everytime the active element changes, I have change the DOM structure, as you suggested, by removing the current active element and then appending the new one.
Oh, if you first load all the elements into the DOM, convert it, and then re-append them as needed, this is a bad idea.
I would e.g. format the data as JSON and add it as a data- attribute on some element on the page. Then you don't have as many elements on the page to begin with!
0

I think the only dom elements you might want to apply lazy rendering are those that require media content like image, audio, video,etc. For those, search for a lazy loading js library that load the content of that element when you show that element. Also you could leave the element loaded into the page and hidden, but maybe if there are too many media elements it might be a bad use of memory.

Lastly, you could use React.js for this since it's main job is to dinamically render the diff between two dom trees, this might give some great improvements in scenarios where you are rendering the same dom element but with slightly different content. You probably knew about this, is there any reason why you decided to go full vainilla.js on this ?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.