Web Analytics Made Easy -
StatCounter function is slowing things down - CodingForum

Announcement

Collapse
No announcement yet.

function is slowing things down

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • function is slowing things down

    Hi I was wondering if the following function can be made to have super performance, as now performance is getting poor under stress testing.
    Thanks for your suggestions!

    Code:
    	function getInventoryDates(cellIDs){
    		var oCell, cellsArray, intCellIndex, objDateRow, strDate
    		strDate = "";
    		cellsArray = cellIDs.split("~");
    		objDateRow = document.getElementById("dateHeading");
    		if(cellsArray[0]!=""){
    			for(var i=0;i < cellsArray.length;i++){
    				oCell = document.getElementById(cellsArray[i]);
    				intCellIndex = oCell.cellIndex;
    				//alert(intCellIndex + " : " + objDateRow.cells(intCellIndex).id);
    				if(strDate==""){
    					strDate = objDateRow.cells(intCellIndex).id;
    				} else {
    					strDate = strDate + "^" + objDateRow.cells(intCellIndex).id;
    				}
    			}
    		}
    		return strDate
    	}

  • #2
    I am removing an unnecessary conditional. I'm also refactoring your for loop to be more efficient:

    Code:
    function getInventoryDates(cellIDs)
    {
      var oCell, cellsArray, intCellIndex, objDateRow, strDate;
      strDate = "";
      cellsArray = cellIDs.split("~");
      objDateRow = document.getElementById("dateHeading");
    
      if (cellsArray[0] != "")
      {
        var imax = cellsArray.length;
        for(var i=0; i < imax; ++i)
        {
          oCell = document.getElementById(cellsArray[i]);
          intCellIndex = oCell.cellIndex;
    
          strDate = strDate + objDateRow.cells(intCellIndex).id;
          objDateRow.cells(intCellIndex).id;
        }
      }
    
      return strDate
    }
    That's one step you can take to make your function more efficient.

    Comment


    • #3
      Also count backwards....

      Counting backwards is faster (for some reason) and also does comparisons on a literal instead of variable. Also allows for removal of cellsArray.length cache variable.

      Unrolling the loop makes it faster, but consumes more ram.

      PHP Code:
      function getInventoryDates(cellIDs)
      {
        var 
      oCellcellsArrayintCellIndexobjDateRowstrDate;
        
      strDate "";
        
      cellsArray cellIDs.split("~");
        
      objDateRow document.getElementById("dateHeading");

        if (
      cellsArray[0] != "")
        {
          for(var 
      i=cellsArray.length-1> -1i--)
          {
            
      oCell document.getElementById(cellsArray[i]);
            
      intCellIndex oCell.cellIndex;
            
      strDate objDateRow.cells(intCellIndex).id strDate;
            
      objDateRow.cells(intCellIndex).id;
            if(--
      > -1){
              
      oCell document.getElementById(cellsArray[i]);
              
      intCellIndex oCell.cellIndex;
              
      strDate objDateRow.cells(intCellIndex).id +strDate;
              
      objDateRow.cells(intCellIndex).id;
            }
          }
        }

        return 
      strDate

      You can unroll more times in order to speed it up further.

      Comment


      • #4
        Thanks Beagle!

        Thanks Beagle and VortexCortex,

        both solutions are brilliant. now which one to choose or maybe i'll mix the philosphies togther?.... hmm

        Comment


        • #5
          Iterating backwards is not faster inherently. It's faster because it requires one less variable assignment than the solution I proposed and usually compares against a literal instead of a variable, as you said. I didn't choose to run the loop backwards because of the way the code was written, it appeared that it needed to be looped forward, and I didn't want to muck with it.

          I will also contend that you're unrolling of the loop speeds up the process. The loop logic you wrote requires a decrement and a conditional before entering into the code block, which is EXACTLY the same as what the for loop does. I'll go do some research, but we should run some tests to see if what you claim is true. Algorithmically, you don't gain anything by adding the conditional you added.

          Comment


          • #6
            Backwards for loops are FASTER on average. - I have proof

            I have done extensive research.

            Although I do not know why, decrementing a for loop is faster than incrementing it.

            Here is a test page if you don't believe me.
            Code:
            <html>
            <head>
            <title>Loop Speed Testing...</title>
            <script type="text/javascript"><!--
            var forInput,forResult,backResult,optResult,condResult,superResult;
            function forLoop(){
            	var start = new Date();
            	var y=1;
            	x = parseInt(forInput.value);
            	for(var i=y;i<=x;i++){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            	}
            	var end = new Date();
            	forResult.value = end.getTime() - start.getTime();
            }
            
            function backLoop(){
            	var start = new Date();
            	var y=1;
            	x = parseInt(forInput.value);
            	for(var i=x;i>=y;i--){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            	}
            	var end = new Date();
            	backResult.value = end.getTime() - start.getTime();
            }
            
            function optLoop(){
            	var start = new Date();
            	x = parseInt(forInput.value);
            	for(var i=x;i>=1;i--){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            	}
            	var end = new Date();
            	optResult.value = end.getTime() - start.getTime();
            }
            
            function condLoop(){
            	var start = new Date();
            	x = parseInt(forInput.value);
            	var y=1;
            	for(var i=x;i>=y;i--){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            		if(--i >= y){
            			var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            		}
            	}
            	var end = new Date();
            	condResult.value = end.getTime() - start.getTime();
            }
            
            function superLoop(){
            	var start = new Date();
            	x = parseInt(forInput.value);
            	var y=4;
            	var i;
            	if(x>=4)for(i=x;i>=y;i-=4){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/(i-1)))));
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/(i-2)))));
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/(i-3)))));
            	}
            	y=1;
            	for(i=i;i>=y;i--){
            		var d = Math.round(Math.sin(Math.sqrt(Math.cos(Math.PI/i))));
            	}
            	var end = new Date();
            	superResult.value = end.getTime() - start.getTime();
            }
            
            function init(){
            	forInput = document.getElementById("forInput");
            	forResult = document.getElementById("forResult");
            	backResult = document.getElementById("backResult");
            	optResult = document.getElementById("optResult");
            	condResult = document.getElementById("condResult");
            	superResult = document.getElementById("superResult");
            }
            //--></script>
            </head>
            <body onload="init()">
            For Loop Iterations <input type="text" size="10" id="forInput" value="100000"><br>
            <button onclick="forLoop()">Test Forward</button> Result <input type="text" id="forResult" size="10">ms<br>
            <button onclick="backLoop()">Test Backwards</button> Result <input type="text" id="backResult" size="10">ms<br>
            <button onclick="optLoop()">Test Optimized Backwards</button> Result <input type="text" id="optResult" size="10">ms<br>
            <button onclick="condLoop()">Test Unrolled w/ Conditional</button> Result <input type="text" id="condResult" size="10">ms<br>
            <button onclick="superLoop()">Test 4 x Unrolled w/o Conditional</button> Result <input type="text" id="superResult" size="10">ms<br>
            <button onclick="forLoop();backLoop();condLoop();optLoop();superLoop()">Test all</button>
            <p>The first two for loops are identical except that the second loops counts backwards instead of forwards.  This is faster at higher iterations.</p>
            <p>The third for loop is the same as the second for loop except with a slight optimization replacing a cached value with a literal. Provides little or no improvement over second loop.</p>
            <p>The fourth loop is the second loop unrolled one time with an if conditional block inserted.
            <p>The fifth loop is the second loop unrolled 4 times with an additional loop at the end to pick up iterations not divisible by 4.</p>
            <p>Note: In IE there is little or no difference in speed for the 2nd thru 5th loops, test with Netscape / FF to see varried improvements.
            </body>
            </html>
            Take my code above for a spin and see for yourself.

            I believe the largest performance hit is comming from string concatenation in the original post... place strings into an array and then join to concatenate all in one go. Example:
            Code:
            function getInventoryDates(cellIDs)
            {
              var oCell, cellsArray, intCellIndex, objDateRow, strDate;
              strDate = new Array(cellsArray.length); //pre allocate the array too.
              cellsArray = cellIDs.split("~");
              objDateRow = document.getElementById("dateHeading");
            
              if (cellsArray[0] != "")
              {
                for(var i=cellsArray.length-1; i > -1; i--)
                {
                  oCell = document.getElementById(cellsArray[i]);
                  intCellIndex = oCell.cellIndex;
                  strDate[i] = objDateRow.cells(intCellIndex).id;
                  objDateRow.cells(intCellIndex).id;
                  if(--i > -1){
                    oCell = document.getElementById(cellsArray[i]);
                    intCellIndex = oCell.cellIndex;
                    strDate[i] = objDateRow.cells(intCellIndex).id;
                    objDateRow.cells(intCellIndex).id;
                  }
                }
              }
            
              return strDate.join('');
            }
            Last edited by VortexCortex; Oct 7, 2006, 03:09 PM. Reason: Further optimization of original post.

            Comment


            • #7
              The reason is caching, I believe.

              Consider:

              Code:
              all_tags = document.getElementsByTagName ('*');
              
              for (var i = 0; i < all_tags.length; i++)
              {
              }
              The JavaScript engine has to first find the all_tags object. Then it has to look up the length property and its value. To increase speed on up-counting loops, do this:

              Code:
              all_tags = document.getElementsByTagName ('*');
              
              for (var i = 0, j = all_tags.length; i < j; i++)
              {
              }
              offtone.com | offtonedesign.com

              Comment


              • #8
                AaronW: We covered that already, but thanks for clarifying just in case.

                Vortex, I'll test that in IE/FF/Opera on Linux and XP and I'll post my findings in a new thread on the JavaScript forum. Thanks for the test suite.

                Comment

                Working...
                X