dcsimg
www.webdeveloper.com
Results 1 to 9 of 9

Thread: What is the fastest way to write to innerHTML ?

  1. #1
    Join Date
    Jul 2005
    Posts
    31

    What is the fastest way to write to innerHTML ?

    Hello All,

    The Situation:
    I've been working recently with trying to create DIV's on the fly. i.e. a user clicks on an element, and that generates the innerHTML of some DIV on the page.
    For instance, I might have:

    <p><a href="#" onclick="someFunction('theDiv');">Generate</a><p>
    <div id="theDiv"></div>

    Clicking on the Generate link would set the innerHTML of the div named theDiv to be set to some arbitrary string (lets say its the string below):

    <p>Hello World for the first time.</p>


    The Problem:

    The problem I am having is when I try to write the "Hello World" string to the innerHTML several hundred/thousand times. Basically I loop through a list, and write the "hello world" top a string until the loop is done, and then I write it out to innerHTML. This causes the browser to slow down and become unresponsive for a few seconds. The greater the number of lines the longer the pause/slowdown.

    My Question:

    Is there a faster way to write to the document? Using the DOM is too slow, and I don't need to programatically access any of these newly created nodes so I don't think that will help any. I haven't seen chunking the data out to innerHTML make much of a diffrrence (i.e. writing to innerHTML every X number of lines) from my brief tests either.

    Thanks in advance,
    --james

  2. #2
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    What is the fastest way to write to innerHTML ?
    Probably the fastest way is to use DOM methods instead of innerHTML, in case of huge text and/or tag elements.

  3. #3
    Join Date
    Jul 2005
    Posts
    31

    Test Results

    Thanks for the response Kor. I've read that innerHTML was usually faster than the DOM, but just to check I whipped out the following test case:

    HTML Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    	<title>JS Test</title>
    <script type="text/javascript">
    	function makeDiv(oParent){
    		var d1=new Date().getTime();
    				for(var i=0;i<1300;i++){
    					var oP=document.createElement("p");
    					var oB=document.createElement("b");
    					var oBR=document.createElement("br");
    					var oA=document.createElement("a");
    					var oI=document.createElement("img");
    					oI.src='nc.gif';
    					oP.appendChild(oB);					
    					oP.appendChild(oBR);
    					oP.appendChild(oA);
    					oP.appendChild(oI);
    					oB.appendChild(document.createTextNode("Text for testing. Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum. Para #" + (i + 1)));
    					oA.appendChild(document.createTextNode("Text for testing. Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum. Link #" + (i + 1)));
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		alert(d2-d1);
    	}
    	
    function makeDiv2(oParent){
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=0;i<1300;i++){
    					str+='<p><b>Text for testing. Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum. Para #  '+(i+1)+'</b><br><a> Text for testing. Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum.Lorem Ipsum. Link # '+(i+1)+'</a><img src="nc.gif"></p>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		alert(d2-d1);
    }
    </script>
    </head>
    <body>
    <h3>Div is below</h3>
    <p><a href="#" onclick="makeDiv(window.document.getElementById('me'));">Start DOM</a></p>
    <p><a href="#" onclick="makeDiv2(window.document.getElementById('me'));">Start innerHTML</a></p>
    <div id="me"></div>
    </body>
    </html> 

    The results were as follows:

    Using the DOM, the execution times were: 3725ms,3690ms,3643ms, and 3530ms.
    Using innerHTML the execution times were: 1538ms,1576ms,1488ms, and 1518ms

    So this test bears out that innerHTML is usually faster. I don't use the DOM that much so I'm having to assume that code I snagged is the "correct" way to do it using the DOM (and also the most efficient)

    Thanks again though for the response.

    -james

  4. #4
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    If you have tested, that it should be so... In that case, the sigle thing that could speed a little bit the process is to loop in reverse. It will speed the process about 2 times. Counting down to 0 is faster that counting up to a number of iteration.

    for(var i=1299;i>=0;i--){
    ...
    }

    You can also use the flipped loop with reverse count, using do-while instead of a for() loop

    var i=1299;
    do
    {
    ......
    }
    while (--i);
    }

  5. #5
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    the fastest way to loop seems to be the so called "Duff's" method... Which is a combination of flipped reverse loop and switch/ cases but the disadvantage is that you should write 1300 case lines...
    Last edited by Kor; 07-12-2005 at 03:35 AM.

  6. #6
    Join Date
    Aug 2004
    Location
    Derby, England
    Posts
    297
    I agree that innerHTML is faster than DOM.

    See. http://www.quirksmode.org/dom/innerhtml.html

    This causes the browser to slow down and become unresponsive for a few seconds.
    I am not sure from your coment whether it is the innerHTML that is the problem, or the loop creating the string.

    If it is the loop creating the string, then as well as Kor's more efficient loop strategies, you should note that concatenation of strings can also be quite slow

    i.e. str=str+"another string"

    The alternative is to add all the strings to an array, and then join the array.

    var aStr=new Array();
    aStr.push("another string");
    aStr.push("another string");
    aStr.push("another string");
    var sString=aStr.join("");

  7. #7
    Join Date
    Jul 2005
    Posts
    31

    some results

    Thanks all for replying. I've been doing some testing and here are the results so far.
    *( '++' and '--' is the increment method used in a for loop, going to try do...while next. It looks like one of the things that really has an affect on the speed is the existence of images in the created element. Other than not using images, setting the images as the background of a DIV, and then making that div be the same size as the full image seems to have the most speed increase. Once again however, using innerHTML, seems to give a pretty decent speed increase. I'm going to run some more tests using the other tips I've gotten from the forum. Thanks again for all of your help. The code is below if you would like to repeat the tests.)

    DOM: ++image: 6091 ms
    DOM: ++image(as background): 1245 ms
    DOM: ++No Image: 1416 ms
    DOM: --image: 5811 ms
    DOM: --image(as background): 1232 ms
    DOM: --No Image: 1091 ms
    innerHTML: ++Image: 2630 ms
    innerHTML: ++Image (as background): 334 ms
    innerHTML: ++Image (no image): 359 ms
    innerHTML: --Image: 2540 ms
    innerHTML: --Image (as background): 341 ms
    innerHTML:--Image (no image): 365 ms


    (I have to post the actual code in another post due to size restrictions

  8. #8
    Join Date
    Jul 2005
    Posts
    31

    If you'd like to duplicate

    BTW if your results are signifigantly different than mine, please let me know. Or if you catch something I've done wrong. Thanks again.

    Code:
    HTML Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    	<title>JS Test</title>
    	<style type="text/css">
    	body{
    		font-size:10pt;
    		font-family:Verdana,Helvetica,Arial,sans-serif;
    		color:#333333;
    	}
    	.indDiv {
    		border:1px solid #111111;
    		background-color:#eeeeee;
    		margin:2px 10px 2px 10px;
    	}
    	.hmmstar{
    		border:1px solid #000000;
    		width:20px;
    		height:20px;
    		text-align:center;
    		font-size:8pt;
    		font-family:sans-serif;
    		font-weight:700;
    		margin:3px;
    		padding:0px;
    	}	
    .starBG{
    float:right;
    height:18px;
    		width:18px;
    background-image:url('http://groups-beta.google.com/img/watched_y.gif');
    }	
    .star{
    	float:right;
    }	
    	
    	.pTimer{
    		float:left;
    		border:1px solid #333333;
    		width:350px;
    		height:500px;
    		padding:5px;
    		margin-right:10px;
    	}
    .sLink{
    	border:1px solid #333333;
    	padding:3px 10px 3px 10px;
    	text-decoration:none;
    	color:#0000aa;
    	font-family:Verdana,Helvetica,Arial,sans-serif;
    	font-size:10pt;
    }
    a.sLink:hover{
    		background-color:#dddddd;
    }
    .targetDiv{
    	float:right;
    	overflow:auto;
    	margin-right:20px;
    	height:500px;
    	width:400px;
    	border:1px solid #333333;
    }
    </style>
    <script type="text/javascript">
    	var iterations=2500;
    	var theText='This is the text we will test with. BTW, hello world.';
    	function clearDiv(){
    		window.document.getElementById('tDiv').innerHTML='';
    		//using DOM
    		var t=window.document.getElementById('tDiv');
    		if (t && t.hasChildNodes && t.removeChild) {	
    			while (t.hasChildNodes()) {
    				t.removeChild(node.firstChild);
    			}
    		}
    
    	}
    	function makeDiv(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=0;i<iterations;i++){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oPara = document.createElement('p');
    					oPara.appendChild(document.createTextNode(theText));
    					var oImg = document.createElement('img');
    					oImg.className='star';
    					oImg.height=18;
    					oImg.width=18;
    					oImg.className='starBG';
    					oImg.src='http://groups-beta.google.com/img/watched_y.gif';
    					oP.appendChild(oImg);
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: ++image: '+(d2-d1)+' ms<br>';
    	}
    
    	function makeDiv1(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=0;i<iterations;i++){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oImg = document.createElement('div');
    					oImg.className='starBG';
    					var oPara = document.createElement('p');
    					oPara.appendChild(oImg);
    					oPara.appendChild(document.createTextNode(theText));
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: ++image(as background): '+(d2-d1)+' ms<br>';
    	}
    	
    		function makeDiv2(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=0;i<iterations;i++){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oImg = document.createElement('div');
    					oImg.appendChild(document.createTextNode('*'));
    					oImg.className='star'
    					var oPara = document.createElement('p');
    					oPara.appendChild(oImg);
    					oPara.appendChild(document.createTextNode(theText));
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: ++No Image: '+(d2-d1)+' ms<br>';
    	}
    	
    	function makeDiv3(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=iterations;i>0;i--){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oPara = document.createElement('p');
    					oPara.appendChild(document.createTextNode(theText));
    					var oImg = document.createElement('img');
    					oImg.src='http://groups-beta.google.com/img/watched_y.gif';
    					oPara.appendChild(oImg);
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: --image: '+(d2-d1)+' ms<br>';
    	}
    	
    		function makeDiv4(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=iterations;i>0;i--){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oImg = document.createElement('div');
    					oImg.className='starBG';
    					var oPara = document.createElement('p');
    					oPara.appendChild(oImg);
    					oPara.appendChild(document.createTextNode(theText));
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: --image(as background): '+(d2-d1)+' ms<br>';
    	}
    	
    		function makeDiv5(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    				for(var i=iterations;i>0;i--){
    					var oP=document.createElement("div");
    					oP.className='indDiv';
    					var oImg = document.createTextNode('*');
    					var oPara = document.createElement('p');
    					oPara.appendChild(document.createTextNode(theText));
    					oPara.appendChild(oImg);
    					oP.appendChild(oPara);
    					oParent.appendChild(oP);
    				}
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='DOM: --No Image: '+(d2-d1)+' ms<br>';
    	}
    	
    	function makeDiv6(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=0;i<iterations;i++){
    				str+='<div class="indDiv"><img class="star" src="http://groups-beta.google.com/img/watched_y.gif"><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML: ++Image: '+(d2-d1)+' ms<br>';
    }
    	
    	
    function makeDiv7(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=0;i<iterations;i++){
    				str+='<div class="indDiv"><div class="starBG"></div><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML: ++Image (as background): '+(d2-d1)+' ms<br>';
    }
    	
    function makeDiv8(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=0;i<iterations;i++){
    				str+='<div class="indDiv"><div class="star">*</div><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML: ++Image (no image): '+(d2-d1)+' ms<br>';
    }	
    
    function makeDiv9(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=iterations;i>0;i--){
    				str+='<div class="indDiv"><img class="star" src="http://groups-beta.google.com/img/watched_y.gif"><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML: --Image: '+(d2-d1)+' ms<br>';
    }
    	
    	
    function makeDiv10(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=iterations;i>0;i--){
    				str+='<div class="indDiv"><div class="starBG"></div><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML: --Image (as background): '+(d2-d1)+' ms<br>';
    }
    	
    function makeDiv11(oParent){
    		clearDiv();
    		var d1=new Date().getTime();
    		var str=new String();		
    		for(var i=iterations;i>0;i--){
    				str+='<div class="indDiv"><div class="star">*</div><p>'+theText+'</p></div>';
    		}
    		oParent.innerHTML=str;
    		var d2=new Date().getTime();
    		window.document.getElementById('timer').innerHTML+='innerHTML:--Image (no image): '+(d2-d1)+' ms<br>';
    }	
    </script>
    
    </head>
    
    <body>
    
    
    <div id="tDiv" class="targetDiv"></div>
    
    <div id="timer" class="pTimer"></div>
    
    <p><a href="#" class="sLink" onclick="makeDiv(window.document.getElementById('tDiv'));">DOM: ++image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv1(window.document.getElementById('tDiv'));">DOM: ++image (as background)</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv2(window.document.getElementById('tDiv'));">DOM: ++No Image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv3(window.document.getElementById('tDiv'));">DOM: --image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv4(window.document.getElementById('tDiv'));">DOM: --image (as background)</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv5(window.document.getElementById('tDiv'));">DOM: --No Image</a></p>
    
    <p><a href="#" class="sLink" onclick="makeDiv6(window.document.getElementById('tDiv'));">innerHTML: ++image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv7(window.document.getElementById('tDiv'));">innerHTML: ++image (as background)</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv8(window.document.getElementById('tDiv'));">innerHTML: ++No Image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv9(window.document.getElementById('tDiv'));">innerHTML: --image</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv10(window.document.getElementById('tDiv'));">innerHTML: --image (as background)</a></p>
    <p><a href="#" class="sLink" onclick="makeDiv11(window.document.getElementById('tDiv'));">innerHTML: --No Image</a></p>
    
    
    </body>
    </html>

  9. #9
    Join Date
    Jul 2005
    Posts
    31

    More info

    After looking at everything it has *really* sped up, well I should say the time it takes the functions to excute and be timed has sped up.

    My bottleneck is now the time it takes the browser to render the information.

    Basicall i write this information (via innerHMTL or the DOM) to a div who has its display style set to "none".

    Once the data has been pulled, and the div has been populated, i just set the style to be "block". This has the effect of making all of the newly generated HTML be visible. From all my testing, this is the bottleneck. The redering engine/javascript get so bogged down that the actual timer stops while the HTML is rendered. So when all is said and done, my timer t ells me that 1200 ms have elapsed, but measuring with a watch, tells me that approximately 52 seconds have gone by since the browser locked up/bogged down/stopped responding after my click.

    Does anyone have any experience with the actual way the browser handle the rendering calls?

    I've got a few options I can explore (chunking the data to the layer every few seconds, a more>>> button, etc.)


    Thanks,

    -james

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles