Question about performance in IE

G

Gui Lloyd

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>
 
L

Lee

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.
 
Y

Yann-Erwan Perio

Lee wrote:

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.
 
M

Mick White

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
 
R

Richard Cornford

Gui 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?

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:-

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.
 
G

Guilherme Lloyd

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!
 
G

Grant Wagner

Mick said:
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 <[email protected]>

* 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
 
M

Mark Preston

Gui said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top