Question about performance in IE

Discussion in 'Javascript' started by Gui Lloyd, Jun 15, 2004.

  1. Gui Lloyd

    Gui Lloyd Guest

    I have a problem with performance in IE.
    The script above works quite fine when the table has a small number of
    elements, but, when the table has 2500 elements, when I click in the
    checkbox of the table header (to select all the checkboxes in table),
    the script demands at least 3 minutes to execute. I tested the same
    script in Mozilla and the response time is much more faster. Does
    anyone has an idea?

    <script>
    function checkFieldAll(fieldName, checked) {

    // Defining the prefix and sufix of the indexed parameter
    var prefix = fieldName.substring( 0,
    fieldName.indexOf('[') );
    var sufix = fieldName.substring( fieldName.indexOf(']',
    prefix) + 1 );

    // Looking for the parameters to be treated matching the
    sufix and prefix
    var allFields = this.document.forms[0].elements;
    var fields = new Array();
    for (i = 0; i < allFields.length; i++) {
    var name = allFields.name;
    if(name != undefined){
    if (name.indexOf(prefix) == 0 &&
    name.indexOf(sufix) > name.indexOf(prefix)) {
    var elem = allFields;
    fields.push(elem);
    }
    }
    }

    // check/uncheck the fields
    for (i = 0; i < fields.length; i++) {
    fields.checked = checked;
    }
    }

    function onChangeCheckAll (checkObject, fieldName) {
    checkFieldAll(fieldName, checkObject.checked);
    }
    </script>

    and in HTML I have something like:

    <table id="lockingsList" class="noScrolledList" >
    <tr class="noScrolledList">
    <th class="noScrolledListHeader" rowspan="2" >
    <input type="checkbox" onclick="javascript:eek:nChangeCheckAll(this,
    'lockingsList[].isChecked');">
    </th>
    <th class="noScrolledListHeader" rowspan="2" >
    Mnemonic
    </th>
    </tr>

    <tr class="listCellAlternate1">
    <td class="listCell">
    <input type="checkbox" name="lockingsList[0].isChecked"
    value="on" id="lockingsList_0_isChecked">
    <input type="hidden"
    name="lockingsList[0].isChecked__generated_field__"
    value="__FALSE_CHECKBOX__"
    id="lockingsList_0_isChecked__generated_field__">
    </td>
    <td class="listCell"><span
    id="lockingsList_0_mnemonic">P09_H67-1</span>
    </td>
    </tr>
    ......
    </table>
     
    Gui Lloyd, Jun 15, 2004
    #1
    1. Advertising

  2. Gui Lloyd

    Lee Guest

    Gui Lloyd said:
    >
    >I have a problem with performance in IE.
    >The script above works quite fine when the table has a small number of
    >elements, but, when the table has 2500 elements, when I click in the
    >checkbox of the table header (to select all the checkboxes in table),
    >the script demands at least 3 minutes to execute. I tested the same
    >script in Mozilla and the response time is much more faster. Does
    >anyone has an idea?


    In the first place, IE is just slower at some things than Mozilla.
    However, you've got some inefficiencies:


    > if (name.indexOf(prefix) == 0 &&
    >name.indexOf(sufix) > name.indexOf(prefix))


    The second comparison never executes unless the first one is true.
    That means that there's no reason to execute name.indexOf(prefix)
    a second time. You know that the value must be 0:

    if (name.indexOf(prefix) == 0 && name.indexOf(sufix) > 0 ) {

    Why copy the elements into an array and then loop through that
    array to set the value of checked? Just set each one as you
    find it.

    There are probably other things about the page that can be
    used to improve performance. If you want to set all of the
    checkboxes in the form, then don't bother looking at their
    names, just check to see if the type attribute is "checkbox".

    Similarly, if you have two columns of checkboxes, and only want
    to set one, then you should be able to just set every other
    checkbox. Or if you know that there are other fields, but that
    every 5th one is a checkbox, you can loop through touching only
    every 5th element, etc.
     
    Lee, Jun 15, 2004
    #2
    1. Advertising

  3. Lee wrote:

    <snip excellent advice>

    > There are probably other things about the page that can be
    > used to improve performance.


    One that should increase the speed considerably is the for loop:

    Change from
    for (i = 0; i < allFields.length; i++) {
    to
    for (var i = allFields.length; i--;) {


    Regards,
    Yep.
     
    Yann-Erwan Perio, Jun 15, 2004
    #3
  4. Gui Lloyd

    Mick White Guest

    Yann-Erwan Perio wrote:


    >
    > One that should increase the speed considerably is the for loop:
    >
    > Change from
    > for (i = 0; i < allFields.length; i++) {
    > to
    > for (var i = allFields.length; i--;) {
    >



    or:
    x=allFields.length;
    while(x--){ do stuff with x}

    Mick
     
    Mick White, Jun 16, 2004
    #4
  5. Gui Lloyd wrote:
    > I have a problem with performance in IE.
    > The script above works quite fine when the table has a small number of
    > elements, but, when the table has 2500 elements, when I click in the
    > checkbox of the table header (to select all the checkboxes in table),
    > the script demands at least 3 minutes to execute. I tested the same
    > script in Mozilla and the response time is much more faster. Does
    > anyone has an idea?


    On of the things that makes IE slowwer4 than Mozilla in some respects is
    the fact that IE uses a list-like implementation for its object, while
    Mozilla (and most other browsers) use a hash-table-like implementation.
    The effect is that as IE's objects get bigger it takes longer to resolve
    property names (of the properties towards the end of the list), While a
    hash-table-like object takes about as long to resolve property names
    regardless of size (or at least the difference isn't noticeable). The
    objects suffering that problem in your code are the - element -
    collection of the form and the Array. As Lee said, you don't need the
    Array at all. You can also loose the second look-up in the elements
    collection if you assign - allFields - a reference to the form
    control to a local variable at that point.

    As Yep suggested, counting down in the - for - loop will be quicker
    because you don't have to resolve the length property on each iteration
    (and making - i - a local variable will make its use fractionally
    faster. But you might also try a - do{ ... }while(); - loop in its place
    as they can be faster than - for - loop (also counting down).

    > <script>
    > function checkFieldAll(fieldName, checked) {
    >
    > // Defining the prefix and sufix of the indexed parameter


    Formatting code with a consideration of how newsreaders will present it
    is usually a good idea when posting to Usenet. See the FAQ:-

    <URL: http://jibbering.com/faq/ >

    > var prefix = fieldName.substring( 0,
    > fieldName.indexOf('[') );
    > var sufix = fieldName.substring( fieldName.indexOf(']',
    > prefix) + 1 );


    This looks wrong, and garbled code presentation is hiding it from other
    observers. Theoretically - prefix, has been assigned a string value, yet
    here you are using it as an argument to - indexOf -, and in the context
    of the "position". ECMA 262 calls for the positin argument to be subject
    to a call to the internal - ToInteger - function. If the string value
    of - prefix - represents an integer number then the result will be a
    number, but if - prefix - is a string that cannot be type-converted to a
    number by javascript the call to - ToInteger - will first convert that
    string to the number NaN and then return zero (as it is specified to do
    for number that are NaN).

    >
    > // Looking for the parameters to be treated matching the
    > sufix and prefix
    > var allFields = this.document.forms[0].elements;
    > var fields = new Array();
    > for (i = 0; i < allFields.length; i++) {
    > var name = allFields.name;


    So at this point:-

    var elem = allFields;
    var name = elem.name;

    > if(name != undefined){


    The - name - property of a form control element is of string type. It
    will be an empty string if no name was assigned, except maybe on some
    unusual implementations where it might actually be undefined. However,
    Type-converting comparison will never consider a string value (even an
    empty string) as equal to undefined, so this test will be passed by all
    elements under most circumstances. If you want to exclude controls that
    have no defined name attribute (so an empty string) and exclude the
    possibility that the corresponding name property may be undefined (for
    absolute safety) then a type-converting test will probably be quickest:-

    if(name){

    > if (name.indexOf(prefix) == 0 &&
    > name.indexOf(sufix) > name.indexOf(prefix)) {


    As Lee said, the second execution of - name.indexOf(prefix) - is
    unnecessary as you already know that it will return zero. The comparison
    in the first test may also not be needed as - !name.indexOf(prefix) -
    will only be true when - name.indexOf(prefix) == 0 - is true. I don't
    know whether that would actually be quicker, there won't be much in it
    either way.

    Javascript also has the - lastIndexOf - method for String objects, and
    if you are expecting to find a suffix you would expect to find it at the
    end of a string. The balance of probability is that - lastIndexOf -
    implementations will search strings from end to start, and so fins
    suffixes quicker than - indexOf - (each will take (almost) exactly as
    long as the other when they fail to find a match) :-

    if ((!name.indexOf(prefix)) && (name.lastIndexOf(sufix) > 0)){


    > var elem = allFields;
    > fields.push(elem);


    If - elem - was assigned earlier it does not need to be re-resolved
    against the (large) elements collection at this point. Assuming you drop
    the - fields - array, all that is left to do here is set the checked
    property:-

    elem.checked = checked;

    <snip>

    Combining all suggested changes may produce:-

    function checkFieldAll(fieldName, checked){
    var prefix = fieldName.substring( 0, fieldName.indexOf('[') );
    var sufix = fieldName.substring(fieldName.lastIndexOf(']') + 1);
    var allFields = this.document.forms[0].elements;
    var name, elem, i;
    if((i = allFields.length)){
    do{
    elem = allFields[--i];
    name = elem.name;
    if(
    (name = elem.name) &&
    (!name.indexOf(prefix)) &&
    (name.lastIndexOf(sufix) > 0)
    ){
    elem.checked = checked;
    }
    }while(i);
    }
    }

    Richard.
     
    Richard Cornford, Jun 16, 2004
    #5
  6. Thanks a lot Lee, Yann, Mick and Richard.
    The main problem was really in the "for (i = 0; i < allFields.length;
    i++)", but all the suggestions improved a lot the code.
    Now the script takes 2 seconds with 2500 elements in table. Thanks a lot
    again. Cheers.


    *** Sent via Devdex http://www.devdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Guilherme Lloyd, Jun 16, 2004
    #6
  7. Gui Lloyd

    Grant Wagner Guest

    Mick White wrote:

    > Yann-Erwan Perio wrote:
    >
    > >
    > > One that should increase the speed considerably is the for loop:
    > >
    > > Change from
    > > for (i = 0; i < allFields.length; i++) {
    > > to
    > > for (var i = allFields.length; i--;) {
    > >

    >
    > or:
    > x=allFields.length;
    > while(x--){ do stuff with x}
    >
    > Mick


    <script type="text/javascript">
    for (var test = 0; test < 5; test++) {
    document.write('<p>Test: ' + test + '<br>');

    var start = new Date();
    for (var i = 100000; i--;) { var x = 0; }
    document.write('for 99999 to 0: ' + ((new Date()).getTime() -
    start.getTime()) + '<br>');
    var start = new Date();
    var i = 100000;
    while(i--) { var x = 0; }
    document.write('while 99999 to 0: ' + ((new Date()).getTime() -
    start.getTime()) + '<br>');
    var start = new Date();
    for (i = 0; i < 100000; i++) { var x = 0; }
    document.write('for 0 to 99999: ' + ((new Date()).getTime() -
    start.getTime()) + '<br>');

    document.write('</p>');
    }
    </script>

    Internet Explorer 6SP1:

    Test: 0; for 99999 to 0: 190; while 99999 to 0: 200; for 0 to 99999:
    251
    Test: 1; for 99999 to 0: 190; while 99999 to 0: 210; for 0 to 99999:
    271
    Test: 2; for 99999 to 0: 210; while 99999 to 0: 200; for 0 to 99999:
    251
    Test: 3; for 99999 to 0: 210; while 99999 to 0: 200; for 0 to 99999:
    271
    Test: 4; for 99999 to 0: 190; while 99999 to 0: 200; for 0 to 99999:
    241

    While both the decrementing loops are slightly faster then the
    incrementing one (on the order of 50ms over 100000 iterations), there
    is no clear winner between the while() and for() loops.

    Firefox 0.9:

    Test: 0; for 99999 to 0: 371; while 99999 to 0: 340; for 0 to 99999:
    461
    Test: 1; for 99999 to 0: 350; while 99999 to 0: 361; for 0 to 99999:
    451
    Test: 2; for 99999 to 0: 340; while 99999 to 0: 361; for 0 to 99999:
    450
    Test: 3; for 99999 to 0: 351; while 99999 to 0: 350; for 0 to 99999:
    471
    Test: 4; for 99999 to 0: 340; while 99999 to 0: 1913; for 0 to 99999:
    451

    The odd result was where Firefox prompted me that a script was causing
    the browser to run slowly. As with IE, decrementing loops are slightly
    faster.

    Opera 7.51:

    Test: 0; for 99999 to 0: 630; while 99999 to 0: 521; for 0 to 99999:
    741
    Test: 1; for 99999 to 0: 511; while 99999 to 0: 481; for 0 to 99999:
    751
    Test: 2; for 99999 to 0: 501; while 99999 to 0: 480; for 0 to 99999:
    751
    Test: 3; for 99999 to 0: 501; while 99999 to 0: 481; for 0 to 99999:
    751
    Test: 4; for 99999 to 0: 501; while 99999 to 0: 610; for 0 to 99999:
    752

    Similar results.

    Netscape 4.78:

    Test: 0; for 9999 to 0: 58444; while 9999 to 0: 211; for 0 to 9999:
    220
    Test: 1; for 9999 to 0: 180; while 9999 to 0: 171; for 0 to 9999: 220
    Test: 2; for 9999 to 0: 180; while 9999 to 0: 180; for 0 to 9999: 221
    Test: 3; for 9999 to 0: 180; while 9999 to 0: 180; for 0 to 9999: 231
    Test: 4; for 9999 to 0: 180; while 9999 to 0: 8703; for 0 to 9999: 240

    Other then the odd first and second to last values (most likely due to
    garbage collection or some other internal activity), the results are
    pretty much on par with the other browsers listed.

    So optimizing your loops by decrementing instead of incrementing
    achieves an execution speed increase of about 25-50%. That
    optimization time could be better spent elsewhere, such as turning a
    mess like:

    for (var i = 0; i < document.forms['formName'].elements.length; i++) {

    var doSomethingWith =
    document.forms['formName'].elements.value;
    }

    into:

    var f = document.forms['formName'].elements;
    for (var i = 0; i < f.length; i++) {
    var doSomethingWith = f.value;
    }

    <form name="myForm">
    <input type="text" name="myText" value="">
    <input type="hidden" name="myHidden" value="">
    <input type="radio" name="myRadio" value="">
    <input type="checkbox" name="myCheckbox" value="">
    <select name="mySelect">
    <option value="1">one</option>
    </select>
    </form>
    <script type="text/javascript">
    for (var test = 0; test < 5; test++) {
    document.write('Test: ' + test + '; ');

    var start = new Date();
    var f = document.forms['myForm'].elements;
    for (var z = 0; z < 100; z++) {
    for (var i = 0; i < f.length; i++) {
    var x = f.value;
    }
    }
    document.write('cached reference: ' + ((new Date()).getTime() -
    start.getTime()) + '; ');

    var start = new Date();
    for (var z = 0; z < 100; z++) {
    for (var i = 0; i < document.forms['myForm'].elements.length; i++) {
    var x = document.forms['myForm'].elements.value;
    }
    }
    document.write('fully qualified: ' + ((new Date()).getTime() -
    start.getTime()) + '<br>');
    }
    </script>

    Internet Explorer 6SP1:

    Test: 0; cached reference: 50; fully qualified: 171
    Test: 1; cached reference: 50; fully qualified: 180
    Test: 2; cached reference: 50; fully qualified: 180
    Test: 3; cached reference: 40; fully qualified: 181
    Test: 4; cached reference: 50; fully qualified: 180

    The other browsers listed above (with the exception of Netscape 4.78)
    also show an approximate 300-400% increase in speed when accessing
    form elements using a cached reference rather then accessing each
    fully-qualified DOM reference each time. It seems obvious to me where
    a Javascript author's attention should be directed when form
    processing is running slowly.

    --
    | Grant Wagner <>

    * Client-side Javascript and Netscape 4 DOM Reference available at:
    *
    http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/frames.html

    * Internet Explorer DOM Reference available at:
    *
    http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp

    * Netscape 6/7 DOM Reference available at:
    * http://www.mozilla.org/docs/dom/domref/
    * Tips for upgrading JavaScript for Netscape 7 / Mozilla
    * http://www.mozilla.org/docs/web-developer/upgrade_2.html
     
    Grant Wagner, Jun 16, 2004
    #7
  8. Gui Lloyd

    Mark Preston Guest

    Gui Lloyd wrote:

    > I have a problem with performance in IE.
    >

    Rather than dealing with the specific example, I will just say that
    there are - naturally - differences in speed between IE and any other
    browser. In fact, they are all different in some way.

    Your job as a coder is to be sure that your code actually works, not to
    make it work perfectly and at the same speed on every browser. Quite
    simply, you are not in control of the browsers used for your code or of
    the speed of the browsers either. That is up to (a) the client) and (b)
    the browser developers.
     
    Mark Preston, Jun 18, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Don Beal
    Replies:
    13
    Views:
    850
    Richard Grimes [MVP]
    Sep 29, 2003
  2. jm
    Replies:
    1
    Views:
    519
    alien2_51
    Dec 12, 2003
  3. Cris Rock

    Performance related Question.....

    Cris Rock, Feb 12, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    318
    Stefano Mostarda
    Feb 12, 2004
  4. cjl
    Replies:
    3
    Views:
    999
    John Nagle
    May 21, 2007
  5. Software Engineer
    Replies:
    0
    Views:
    348
    Software Engineer
    Jun 10, 2011
Loading...

Share This Page