locked
speed - Dom Methods for creating elements RRS feed

  • Question

  • First of all i have to say that DOM Methods in Internet Explorer are very slow in comparison to Mozilla there is a very big difference altough running the script in ie9 mode brings some non remarkable little speed improvement.
     
    My question is about understanding THE Adding of elements into the  DOM to improve my scripts and i already know that innerHTML is the fastest way to do that but its about DOM Methods.
     
    I first thought that the Layout of every element with is created with document.createElement will not be calculated until it is appended to the DOM and when it is append it results in one calculation like you append it with innerHTML. I thought that because it isnt visible til you append it and for that reason why calculate the Layout but i was wrong as the following example shows

    var p=document.createElement("p");
     
    p.appendChild(document.createTextNode("Hello World"));

    with (p.style)
     
       { color="red"; margin="4px"; padding="8px"; }


    is slower than
     
     
    var p=document.createElement("p");
     
    with (p.style)
     
       { color="red"; margin="4px"; padding="8px"; }
     
    p.appendChild(document.createTextNode("Hello World"));


    My explaination for that was:
     
    That appending a Textnode or childnodes will cause calculation of the P Element's Layout, and if you change the style it will cause a double calculation, because of recalculation.
    so I was wrong, every Element is calculated even it isnt appended to the DOM.
     
    After that i did some more test

    Created some p Elements with Textnodes, appended it to a DIV and then to the Body.

    I thought because of the reasons above, that appending the P Elements to the DIV before appending the DIV to the Body would be faster
    thats why Only the DIV has to be recalculated. if i append the DIV to the Body first, then both DIV and THE BODY have to be recalculated.

    Also apennding the TextNode first to the P Element and then append the PElement to the DIV has to be faster.

    so i was convinced above the following code.

    var div=document.createElement("div");

     
    var p;
     for (var i=0;i<10000;i++)
      {
      p=document.createElement("p");
      p.appendChild(document.createTextNode("Hello World"));
    div.appendChild (p); 
    }
     
     document.body.appendChild(div);
     
    and i tried also the "which i was convinced", slower Code
     
    var div=document.createElement("div");
     document.body.appendChild(div);
     
    var p;
     for (var i=0;i<10000;i++)
      {
      p=document.createElement("p");
      div.appendChild (p);
      p.appendChild(document.createTextNode("Hello World"));
      }
     
    i was dumbfounded, because the second method was faster.
     
    Appending the DIV first to the Body then append The empty P Element to the DIV and for last append the TextNode is faster.
     
    Really, i cant explain that, in my opionion there are more calculations than in the first method but it seems that im wrong.
     
    Can somebody explain that




    Monday, January 23, 2012 1:51 AM

All replies

  • I'm sure some wizard will be along to give you the real answer, but I don't mind embarrassing myself so my GUESS would have been the second way(both times)and the reason in a word would be inheritance. Don't the lowest level nodes inherit attributes/properties from the highest so using the first way this can't be done successfully until the end and you might as well be using tables for page layout. The second way the correct inherited styles would be applied the first time around - as the elements are created. Bit like writing html/css yourself - which do you put on the page first - the highest level div tags or all your p tags? Why? Because the wrong way around, cascading your css later on becomes a nightmare.

     

     

    New mods for this gadget available (bottom of the thread). The site doesn't like me trying to write a novel here so the last version has had to be split over three posts.

    • Edited by mystifeid Monday, January 23, 2012 6:12 AM
    Monday, January 23, 2012 3:16 AM
  • thanx for your post.

    It's seems you are right.

    var div=document.createElement("div");
    div.style.color="red";

    var p=document.createElement("p");
    p.appendChild(document.createTextNode("Hello World"));
    //P Element is created and a TextNode is appended, but its offsetWidth is still 0px
    //Nothing is calculated and its color is black

    alert (p.currentStyle.color+" "+p.offsetWidth+" px");


    div.appendChild (p);
    // append the P Element to the DIV will cause CSS inheritance and P will have the red color

    alert (p.currentStyle.color+" "+p.offsetWidth+" px");

    So creating Elements with document.createElement and appending them will cause no Layout calculation but will cause CSS inheritance, if the Elements are not appended to the DOM at this time.

    Its better to go the OUTER to INNER Way

    ----- But that leaves one question unsolved -----.

    Everyone knows that its better to change the innerHTML one time with the complete HTML.
    because of Layout recalculations.

    So why it isnt better to append the complete DIV to the DOM instead of appending the empty DIV to the DOM and then insert the P Elements and so on?

    When i append an Element to the DOM it's fact that the Layout is calculated.

    Try this.

    var div=document.createElement("div");
    div.style.color="red";

    document.body.appendChild (div);

    var p=document.createElement("p");
    p.appendChild(document.createTextNode("Hello World"));

    div.appendChild (p);
    alert (p.offsetWidth+" px");

    it will show a offsetValue greater than 0. So its calculated.

    That means if i append the DIV first to the BODY it's appended to the DOM

    If i then append all the other stuff,
    the DIV and the BODY Layout has to be recalculated everytime something is new appended, that definitley slows down the action -
    on the other hand you have quicker CSS handling, you dont have to always rewrite the CSS stuff, because you go from OUTER to INNER


    So it leaves me in the opionion that,


    Cascading Style Sheets is very time intensive and its better to go the way of Layout recalculation to avoid INNER to OUTER CSS rewritings

    With innerHTML you have the advantage that nothing is calculated and no inheritance happens until the complete HTML code is appended to the DOM and then calculated at once.

    do you share this?

    You cant realize that with DOM Methods in InternetExplorer.

    I dont know  why the elements get the CSS attributes from their parents even if they are not appended to the dom, i think its not necessary equal to its not necessary to calculate their Layout.

    Wouldnt it be faster to avoid CSS inheritance til DOM appending and then do one step from Outer to inner to write CSS and from inner to outer to calculate the Layout and that for each tree way.

    But thats something only Microsoft knows and i have to less internal knowledge to criticize that

     



    Monday, January 23, 2012 11:32 AM
  • Where's that wizard ?

    div.appendChild (p);

    // append the P Element to the DIV will cause CSS inheritance and P will have the red color

    alert (p.currentStyle.color+" "+p.offsetWidth+" px");

    Looks reasonable to me. How can you know the width of a child when the parent's width is unknown. 
    Everyone knows that its better to change the innerHTML...
    I know it's a shedload easier but I generally try to avoid it like the plague because of the security implications.
    So why it isnt better to append the complete DIV to the DOM instead of...
    Again, try it manually. Get two complex pages of html and transplant a div from one page to the other and see how you go.
    With innerHTML you have the advantage that nothing is calculated and no inheritance happens until the complete HTML code is appended to the DOM and then calculated at once. Do you share this?
    Just do a search typing in two words - innerHTML and security. There's a lot in there that makes me cringe and just not want to go down that road. There's a lot of smart people in the world and if you give them even the slightest chance...
    You cant realize that with DOM Methods in InternetExplorer.
    Don't worry - FF is my default. Has been for years. But I make gadgets and everything changes when you only support one browser so I have a new found respect for IE.
    ...and i have to less internal knowledge to criticize that

    Me too.

     

    It's great to see you so interested but next time if you whip up some complete examples like the ones below, you may just get more help. And instead of the sorcerer's apprentice you might even get a wizard...ie help people to help you.

     

     It's getting a bit old now, but have you looked at this page? Firefox innerHtml methods are about 4ms for me. The W3C methods in FF are about 9ms. All methods in Chrome gave around 9ms. But you are right IE was 60/18 - a lot slower than both the others.

     

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test 1</title>
    <style type="text/css">
    body {margin:0;width:130px;height:100px;}
    </style>
    <script type="text/javascript">
     function test(){
      var oDiv, oP;
      oDiv=document.createElement("div");
      oDiv.style.color="red";
      oP=document.createElement("p");
      oP.appendChild(document.createTextNode("Hello World"));
      oDiv.appendChild(oP);
      prs.innerText=oP.currentStyle.color+" "+oP.offsetWidth+" px";
     }
    </script>
    </head>
    <body>
     <input type="button" value="test" onclick="test();"/>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    </body>
    </html>
    

     

     

     

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test 2</title>
    <style type="text/css">
    body {margin:0;width:130px;height:100px;}
    </style>
    <script type="text/javascript">
     function test(){
      var oDiv, oP;
      oDiv=document.createElement("div");
      oDiv.style.color="red";
      document.body.appendChild(oDiv);
      oP=document.createElement("p");
      oP.appendChild(document.createTextNode("Hello World"));
      oDiv.appendChild(oP);
      prs.innerText=oP.currentStyle.color+" "+oP.offsetWidth+" px";
     }
    </script>
    </head>
    <body>
     <input type="button" value="test" onclick="test();"/>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    </body>
    </html>
    


     





    • Edited by mystifeid Monday, January 23, 2012 2:43 PM
    Monday, January 23, 2012 2:02 PM
  • Where's that wizard
    Put the Code in an HTML file containing the following.
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <body onload="alert(new Date().getTime()-a);">
    </body>
    <script>
    var a=new Date().getTime();
    // Put the code here
    </script>
    

    Start it with IE and you can test for yourself.
    Just do a search typing in two words - innerHTML and security. There's a lot in there that makes me cringe and just not want to go down that road. There's a lot of smart people in the world and if you give them even the slightest chance
    There is no danger using innerHTML, the only thing you have to care is to filter always the User Data - write your own html entities function with regular expression. mask < / > and nothing can happen-
    If you dont filter user data on the server your webpage is a security risk regardless of wether you use DOM Methods or innerHTML, there a lot of other traps you cant step into.
    The big advantage of DOM Methods is that you have a fast synchron script reference to the Object, which is harder to realise with innerHTML (for example you can put ids in the HTML, which took a lot of time to parse and the speed advantage is gone)
    I wrote this thread because im writing HTML Applications and sometimes i have to handle a big amount of Data, which can end in much parsing time if you dont improve your code.
    I dont think that this thread would be interesting for webpage developers which read out small data fragments of server databases, they dont have this problem but it becomes useful if you have a bigger Data Table.
    Monday, January 23, 2012 5:41 PM
  • Thanks for the lesson in sanitizing data. Probably needed that. Perhaps you should have prefaced your original post with your last two sentences...
    Most people want to learn to script/code things in the most efficient manner, I think - it's not just the amount of data but also what you do with it.
    Your 'example' is using a (global!)variable before it has been defined with a script block outside of the body. (Just kidding). Do I really have to make my own examples again ? In your first post it sounds like you've been benchmarking with something - is there a reason you can't share that? I don't owe you anything from a past life do I? Let me check something..
     
     
    Ok.
    Here's 500 repetitions with script block at top and bottom - no difference for me - Chrome=4ms, Firefox=7ms, IE9=25ms. So, back to complaining about how slow IE is, exploring the DOM or finding the tricks you need so you can use innerHTML rapido (I didn't say I never use it!)
     
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test 1</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script>
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<500;i++){
     oDiv=document.createElement("div");
     oDiv.style.color="red";
     document.body.appendChild(oDiv);
     oP=document.createElement("p");
     oP.appendChild(document.createTextNode("Hello World"));
     oDiv.appendChild(oP);}
     alert("time = "+(new Date().getTime()-a));
    }
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
    
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test 2</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script>
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<500;i++){
     oDiv=document.createElement("div");
     oDiv.style.color="red";
     document.body.appendChild(oDiv);
     oP=document.createElement("p");
     oP.appendChild(document.createTextNode("Hello World"));
     oDiv.appendChild(oP);}
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script>
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
    




    • Edited by mystifeid Tuesday, January 24, 2012 3:52 PM
    Monday, January 23, 2012 9:36 PM
  • Do I really have to make my own examples again ? In your first post it sounds like you've been benchmarking with something - is there a reason you can't share that? I don't owe you anything from a past life do I? Let me check something..

     

    I'm sorry for the misunderstanding. you wrote: "where is the wizard" and "if you whip up some complete examples like the ones below, you may just get more help"
    so i posted, how i did the test, for others joining the thread. it wasnt meant that i want you to put the script on the bottom outside of the body, that doesnt matter, its only about i did the test.

    And i appreciate your help, pointing me to also think on CSS inheritance in Addition to calculation of Layouts.

    In my first post i used the following code in my test:

    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    
    <script>
    var a=new Date().getTime();
    var p;
    for (var i=0;i<20000;i++)
    	{
    	p=document.createElement("p");
    
      	with (p.style)
      
    	    {color="red"; margin="4px"; padding="8px";} 
        
    	p.appendChild(document.createTextNode("Hello World"));
     	}
    
    alert (new Date ().getTime()- a);
    </script>
    

    i got 505 ms in IE.

    and for

    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    
    <script>
    var a=new Date().getTime();
    var p;
    for (var i=0;i<20000;i++)
    	{
    	p=document.createElement("p");
    
    	p.appendChild(document.createTextNode("Hello World"));
     	
     	with (p.style)
      
        		{color="red"; margin="4px"; padding="8px";} 
     	}
    
    alert (new Date ().getTime()- a);
    </script>
    

    i got 556 ms

    and the last one i did with cloneNode which is faster when you generate same elements

    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    
    <script>
    var a=new Date().getTime();
    
    var p=document.createElement("p");
    
    with (p.style)
          {color="red"; margin="4px"; padding="8px";} 
    
    var x;
    for (var i=0;i<20000;i++)
    	{
    	x=p.cloneNode(true);
     	x.appendChild(document.createTextNode("Hello World"));
     	}
    
    	alert (new Date ().getTime()- a);
    </script>
    
    i got 283 ms

    Tuesday, January 24, 2012 12:46 AM
  • Ok, sorry for quirky humour which often leads to misunderstanding...and was misunderstanding you just as often...as for providing examples...it just helps...also sleep is getting a little scarce again lately, so you will have to forgive any unintended offence not to mention the big chance that I'm just plain wrong about everything.
     
    So it seems a little incongruous that someone who is interested in efficient scripting would be using something like "with(p.style)" but I thought maybe there might also be other things in play - hence the desire to see everything between your "html" tags. Anyway...never mind, good enough for now. So without even thinking about node creation, I have significantly improved the majority of my test times. (Funny that chrome doesn't like the cloneNode method and goes from being the fastest to slowest)
     
    (And, if you look at what is below maybe you will see the big difference does not come from assigning styles but from the element creation itself. And in the last test, shows IE is actually the fastest with the styles using the cloneNode method, but since it takes so long with the creation this is not such a big deal. However it might be that IE is slower with the creation because it has so many extra non-standard property defaults)
     
    Also, do you ever use JSLint ?
     
    Nice you like "inheritance." But what about the default styles of the objects...
     
    Example - you never have to write...
    p.style.display="block";
    ...because it just is.
     
    So the "p.style" object would seem to be a fairly cumbersome object - perhaps best left alone (then again maybe just using "with" is not a good idea).
     
    I have modified your script blocks and changed just 3 things:
    - don't mix tabs and spaces (no (or negligible) improvement)
    - just the one var statement (no (or negligible) improvement)
    - don't use 'with(p.style)' (improvement)
     
    Anyway, the really GREAT thing is that I am finally free to share in some of your puzzlement at some of the results...and maybe try some other things.
    **************************************************************
    First, these are my results using your scripts
     
    1.
     
    <script>
    var a=new Date().getTime();
    var p;
    for (var i=0;i<20000;i++)
     {
     p=document.createElement("p");
       with (p.style)
      
        {color="red"; margin="4px"; padding="8px";} 
        
     p.appendChild(document.createTextNode("Hello World"));
      }
    alert (new Date ().getTime()- a);
    </script>
     
    ch 310
    ff 460
    ie 694
     
    2.
     
    <script>
    var a=new Date().getTime();
    var p;
    for (var i=0;i<20000;i++)
     {
     p=document.createElement("p");
     p.appendChild(document.createTextNode("Hello World"));
     
      with (p.style)
      
         {color="red"; margin="4px"; padding="8px";} 
      }
    alert (new Date ().getTime()- a);
    </script>
     
    ch 300
    ff 465
    ie 733
     
    3.
     
    <script>
    var a=new Date().getTime();
    var p=document.createElement("p");
    with (p.style)
          {color="red"; margin="4px"; padding="8px";} 
    var x;
    for (var i=0;i<20000;i++)
     {
    x=p.cloneNode(true);
      x.appendChild(document.createTextNode("Hello World"));
      }
    alert (new Date ().getTime()- a);
    </script>
     
    ch 414
    ff 129
    ie 350
     
    ************************************************************
    Figure in brackets is difference between this and corresponding last test - eg (1a - 1)
     
    /*jslint devel: true, browser: true, white: true, plusplus: true, maxerr: 50, indent: 4 */
     
    1a. (modified 1. from above)
     
    <script>
    var a=new Date().getTime(), p, i;
    for(i=0;i<20000;i++){
     p=document.createElement("p");
     p.style.color="red";
     p.style.margin="4px";
     p.style.padding="8px";
     p.appendChild(document.createTextNode("Hello World"));
    }
    alert(new Date().getTime()- a);
    </script>
     
    ch 250 (-60)
    ff 310 (-150)
    ie 612 (-82)
     
    2a. (modified 2. from above)
     
    <script>
    var a=new Date().getTime(), p, i;
    for(i=0;i<20000;i++){
     p=document.createElement("p");
     p.appendChild(document.createTextNode("Hello World"));
     p.style.color="red";
     p.style.margin="4px";
     p.style.padding="8px";
    }
    alert(new Date().getTime()- a);
    </script>
     
    ch 243 (-57)
    ff 306 (-159)
    ie 685 (-48) <- You're right - weird this is slower than first method.
     
    3a. (modified 3. from above)
     
    <script>
    var a=new Date().getTime(), p=document.createElement("p"), i ,x;
    p.style.color="red";
    p.style.margin="4px";
    p.style.padding="8px";
    for(i=0;i<20000;i++){
     x=p.cloneNode(true);
     x.appendChild(document.createTextNode("Hello World"));
    }
    alert(new Date().getTime()- a);
    </script>
     
    ch 402 (-12)
    ff 85  (-44)
    ie 343 (-7)
     
    ****************************************************************************
    Forget about styles - just create element - figure in brackets is difference between this and corresponding last test - eg (1b - 1a)
    Shows that apart from Chrome using cloneNode, the property assignation is taking roughly the same amount of time (within each test )in all 3 browsers. The big difference for IE is in the element creation itself.
     
    1b.
     
    <script>
    var a=new Date().getTime(), p, i;
    for(i=0;i<20000;i++){
     p=document.createElement("p");
     p.appendChild(document.createTextNode("Hello World"));
    }
    alert(new Date().getTime()- a);
    </script>
     
    ch 44 (-206)
    ff 48 (-262)
    ie 330 (-282)
     
    2b. == 1b.
     
    3b.
     
    <script>
    var a=new Date().getTime(), p=document.createElement("p"), i ,x;
    for(i=0;i<20000;i++){
     x=p.cloneNode(true);
     x.appendChild(document.createTextNode("Hello World"));
    }
    alert(new Date().getTime()- a);
    </script>
     
    ch 40 (-362)
    ff 58 (-27)
    ie 320 (-23)
     
     
    Grrrreat - the only road outta here is under about six feet of water :(



    • Edited by mystifeid Tuesday, January 24, 2012 10:24 AM
    Tuesday, January 24, 2012 7:14 AM
  • More tests...please point out mistakes if you see them.
     
    So you have to careful how you use innerHTML...IE seems to be the biggest loser between the first and third tests, but these tests do not seem to take render time into account...(or something - actually this might be just because the script is in the head- nope makes no difference top or bottom)
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test Dom</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<20000;i++){
     oDiv=document.createElement("div");
     document.body.appendChild(oDiv);
     oP=document.createElement("p");
     oP.appendChild(document.createTextNode("Hello World"));
     oDiv.appendChild(oP);}
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 87 <- takes a lot longer to alert
    ff 120 <-fast to alert
    ie 867 <- fast to alert
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test innerHTML</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var i;
    for(i=0;i<1000;i++){
     document.body.innerHTML+="<div><p>Hello World</p></div>";
     }
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    (only 1000 iterations performed but feel free to do 20000 yourself)
    ch 6357 x 20
    ff 1941 x 20
    ie 13164 x 20
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test innerHTML 2</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var i, obj="";
    for(i=0;i<20000;i++){
     obj+="<div><p>Hello World</p></div>";
     }
     document.body.innerHTML+=obj;
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 220 <-alerts very quickly
    ff 77 <- slower than chrome to alert
    ie 154 <- slower than chrome to alert






    • Edited by mystifeid Tuesday, January 24, 2012 4:00 PM
    Tuesday, January 24, 2012 1:45 PM
  • And some more!
     
    Joining some of the statements brings a big speed increase for IE (originally 867 -> down to 495)
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test Dom</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<20000;i++){
     oDiv=document.createElement("div");
     document.body.appendChild(oDiv);
     oP=document.createElement("p");
     oDiv.appendChild(oP).appendChild(document.createTextNode("Hello World"));}
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 95
    ff 128
    ie 495
     
    But joining them all and even getting rid of a few variables makes no difference.
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test Dom</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var i;
    for(i=0;i<20000;i++){
     document.body.appendChild(document.createElement("div")).appendChild(document.createElement("p")).appendChild(document.createTextNode("Hello World"));
     }
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 102
    ff 130
    ie 492
     
    Just joining the appendChild statements but still ending with creating the text node gives a small speed increase
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test Dom</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<20000;i++){
     oDiv=document.createElement("div");
     oP=document.createElement("p");
     document.body.appendChild(oDiv).appendChild(oP).appendChild(document.createTextNode("Hello World"));}
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 83
    ff 122
    ie 480
     
    Totally separating creates and concatenating appends makes no difference
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test Dom</title>
    <style type="text/css">
    body {margin:0;width:130px;}
    </style>
    <script language="javascript" type="text/javascript">
    function test(a){
    var oDiv, oP, i, txt;
    for(i=0;i<20000;i++){
     oDiv=document.createElement("div");
     oP=document.createElement("p");
     txt=document.createTextNode("Hello World")
     document.body.appendChild(oDiv).appendChild(oP).appendChild(txt);
     }
     alert("time = "+(new Date().getTime()-a));
    }
    </script>
    </head>
    <body>
     <div id="prs" style="width:130px;color:#f00">Hi</div>
    <script language="javascript" type="text/javascript">
    window.onload=function(){test(new Date().getTime());};
    </script>
    </body>
    </html>
     
    ch 83
    ff 115
    ie 482



    • Edited by mystifeid Tuesday, January 24, 2012 5:54 PM
    Tuesday, January 24, 2012 5:47 PM
  • So it seems a little incongruous that someone who is interested in efficient scripting would be using something like "with(p.style)"
    As i wrote in my thread Im only testing for faster DOM coding, what you talk about is JScript internal, and this does not take effect if i always use the with statement in all the tests.
    Of course its a little bit faster to write.
    <script>
    
    var a=new Date().getTime();
    
    var p;
    
    for (var i=0;i<20000;i++)
    	
    	{
    	p=document.createElement("p");
    
    	p.appendChild(document.createTextNode("Hello World"));
     	
     	p.style.color="red";
    	p.style.margin="4;
    	p.style.padding="8px";
    	}
    
    
    
    alert (new Date ().getTime()- a);
    </script>
    
    
    it would also be faster to have direct references to the createElement and createTextNode functions and not go over the document object, but thats not what im interested in.
     
    then thanx for your test, i found in interesting that you found out that:
    Joining some of the statements brings a big speed increase for IE (originally 867 -> down to 495)
    but as i looked through it i found a mistake : the two functions dont append the elements in the same order,
    so i doesnt really bring that big improvement.
    867:
    <script language="javascript" type="text/javascript">
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<20000;i++){
    oDiv=document.createElement("div");
    document.body.appendChild(oDiv);
    oP=document.createElement("p");
    oP.appendChild(document.createTextNode("Hello World")); // Here is the mistake
    oDiv.appendChild(oP);} // First append oP to oDiv and then append the TextNode then it is equal to 495
    alert("time = "+(new Date().getTime()-a));
    }
    495: 
    function test(a){
    var oDiv, oP, i;
    for(i=0;i<20000;i++){
    oDiv=document.createElement("div");
    document.body.appendChild(oDiv);
    oP=document.createElement("p");
    oDiv.appendChild(oP).appendChild(document.createTextNode("Hello World"));}
    alert("time = "+(new Date().getTime()-a));
    }

     

    The fastest way with innerHTML is to write the elements in array and then join it.

    var HTML_fragment=new Array (2000);

    for (var i=0;i<2000;i++)

     {HTML_fragment[i]="<div><p>hello world</p></div";}

    document.body.innerHTML=HTML_fragment.join ("");

    Tuesday, January 24, 2012 10:15 PM
  • Thanks for pointing those things out...

     

    "..southeast is awash, with hundreds of roads closed and some homes evacuated amid forecasts of torrential rain extending into next week."

     

    Just woke up and read the above - so it looks like I'm going to have some time to play with it !

    Wednesday, January 25, 2012 2:23 AM
  • Wow, you're right, that is very fast - just about started shaking with excitement there for a sec..except for one little thing (dammit!). Things were a little different the first time around but then had to start again. The second time everything apart from 'unshift' (no surprise) returned virtually the same times. Funny again that Chrome is the slowest.  Seems to make no difference if I use a string or an array (see last test). Also, using .toString().replace(/,/g,"") seems just as fast as .join("") - but it would be impractical in a lot of situations. Anyway, nothing new here, I'm sure.
     
    Copy/pasted yours (except changed '=' to '+='):
     
     var HTML_fragment=new Array(20000), i;
     for(i=0;i<20000;i++){
      HTML_fragment[i]="<div><p>hello world</p></div";
     }
     document.body.innerHTML+=HTML_fragment.join("");
     
    ch 92 <- undesired structure
    ff 52 <-          "           "
    ie 110<-        "           "
     
    Spot the difference (and look at generated sources):
     
     var HTML_fragment=new Array(20000), i;
     for(i=0;i<20000;i++){
      HTML_fragment[i]="<div><p>hello world</p></div>";
     }
     document.body.innerHTML+=HTML_fragment.join("");
     
    ch 210 <- big loser
    ff 58
    ie 156
     
     var HTML_fragment=[], i;
     for(i=0;i<20000;i++){
      HTML_fragment[i]="<div><p>hello world</p></div>";
     }
     document.body.innerHTML+=HTML_fragment.join("");
     
    ch 213
    ff 58
    ie 157
     
     var HTML_fragment=[], i;
     for(i=0;i<20000;i++){
      HTML_fragment.push("<div><p>hello world</p></div>");
     }
     document.body.innerHTML+=HTML_fragment.join("");
     
    ch 212
    ff 58
    ie 156
     
     var HTML_fragment=[], i;
     for(i=20001;i>0;i--){
      HTML_fragment.unshift("<div><p>hello world</p></div>");
     }
     document.body.innerHTML+=HTML_fragment.join("");
     
    ch 309
    ff 266 <-surprise
    ie 255 <-hooray - ie wins one !
     
     var HTML_fragment=[], i;
     for(i=0;i<20000;i++){
      HTML_fragment[i]="<div><p>hello world</p></div>";
     }
     document.body.innerHTML+=HTML_fragment.toString().replace(/,/g,"");
     
    ch 213
    ff 62
    ie 157

     var HTML_fragment="", i;
     for(i=0;i<20000;i++){
      HTML_fragment+="<div><p>hello world</p></div>";
     }
     document.body.innerHTML+=HTML_fragment;
    ch 210
    ff 55
    ie 155




    • Edited by mystifeid Wednesday, January 25, 2012 12:49 PM
    Wednesday, January 25, 2012 11:33 AM
  • you are right array join isnt a speed improvement.

    i read about the join method in an article here on the msdn library yesterday.

    12 Faster DHTML steps-

    they claim it should be the fastest way.....

    nice greetings

     


    Wednesday, January 25, 2012 6:49 PM
  • Don't worry mate, you had me fooled.
     
    Maybe they have done something similar or could be they're still right and it depends on other things too - like complexity of generated structure, complexity of original page, larger number of iterations required etc etc.
     
    You have helped me learn a thing or two, so thanks for that but I think you're going to be just fine from now on and before I am provided the means for embarrassing myself any further, may take this opportunity to depart this thread. (Got the urge to do a coupla other things.)
     
    Take good care of yourself !

    • Edited by mystifeid Thursday, January 26, 2012 12:37 PM
    Thursday, January 26, 2012 3:04 AM