Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Mozilla faster than Internet Explorer

Reply
Thread Tools

Mozilla faster than Internet Explorer

 
 
dhplank
Guest
Posts: n/a
 
      06-02-2005
Hello everyone,

I've developed a calendar program in javascript, and up until now I've
done most of my testing using Mozilla and Firefox. Everything works
fine, but when I try to use Internet Explorer my response time is
sometimes 50 times slower than using Mozilla.

I know I haven't given you much to go by, but I'm not looking for an
answer so much as an approach to debugging the problem. For example,
does anyone here know of a good web site which deals with
browser-specific javascript performance issues?

Thanks in advance for any helpful hints.

 
Reply With Quote
 
 
 
 
RobG
Guest
Posts: n/a
 
      06-02-2005
dhplank wrote:
> Hello everyone,
>
> I've developed a calendar program in javascript, and up until now I've
> done most of my testing using Mozilla and Firefox. Everything works
> fine, but when I try to use Internet Explorer my response time is
> sometimes 50 times slower than using Mozilla.
>
> I know I haven't given you much to go by, but I'm not looking for an
> answer so much as an approach to debugging the problem. For example,
> does anyone here know of a good web site which deals with
> browser-specific javascript performance issues?
>


Performance differences between IE and Firefox can sometimes be found
in unexpected places. One strategy is to isolate loops and test
them, then split them in half, then half again, etc. until the
really slow bits are found.

Replacing loops like:

for (var i=0; i<someThing.length; i++)
// mess with someThing[i]
}

with:

var i=0, x=someThing[i];
do {
// mess with x
} while ( ( x = someThing[++i] ) )

can cause dramatic reductions in processing time, particularly for
large values of someThing.length.

IE tends to be slower than Firefox at DOM operations, but can be
much faster with some others (particularly string stuff in places).

Once you've found the slow bits, post them here and you'll likely get
something better, or just post some of your loops that you think may
be the cause.


--
Rob
 
Reply With Quote
 
 
 
 
mike
Guest
Posts: n/a
 
      06-02-2005
<snip>
Replacing loops like:

for (var i=0; i<someThing.length; i++)
// mess with someThing[i]
}

with:

var i=0, x=someThing[i];
do {
// mess with x
} while ( ( x = someThing[++i] ) )

<snip>

Is this a "Noticeable" difference?

 
Reply With Quote
 
RobB
Guest
Posts: n/a
 
      06-02-2005
dhplank wrote:
> Hello everyone,
>
> I've developed a calendar program in javascript, and up until now I've
> done most of my testing using Mozilla and Firefox. Everything works
> fine, but when I try to use Internet Explorer my response time is
> sometimes 50 times slower than using Mozilla.
>
> I know I haven't given you much to go by, but I'm not looking for an
> answer so much as an approach to debugging the problem. For example,
> does anyone here know of a good web site which deals with
> browser-specific javascript performance issues?


Not particularly browser-specific, but useful:

http://www.peachpit.com/articles/article.asp?p=31567

 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      06-03-2005
Duncan Booth wrote:
> mike wrote:
>
>
>><snip>
>> Replacing loops like:
>>
>> for (var i=0; i<someThing.length; i++)
>> // mess with someThing[i]
>> }
>>
>> with:
>>
>> var i=0, x=someThing[i];
>> do {
>> // mess with x
>> } while ( ( x = someThing[++i] ) )
>>
>><snip>
>>
>>Is this a "Noticeable" difference?
>>
>>

>
>
> Only if '// mess with someThing[i]' repeats the expression many times, e.g.
> inside an inner loop.
>
> Simply replacing the for loop with:
>
> for (var i=0; i<someThing.length; i++) {
> var x = someThing[i];
> // mess with x
> }
>
> will give the same speed improvements without the corresponding drop in
> readability.


No it wont. Getting someThing.length numerous times is slower than
getting it once, so a similar 'for' loop is:

for (var i=0, j=someThing.length; i<j; i++) {

Using x to store the reference to someThing[i] is faster than getting
the reference every time. Initialising x with 'var' every time is not
required but makes no difference to the speed as far as I can tell:

var x;
for (var i=0, j=someThing.length; i<j; i++) {
x = someThing[i];
...

Pre-decrementing i is also faster in most browsers (I believe Opera is
slower in some circumstances), so a while loop can look like:

var i=someThing.length;
var x;
while ( i ) {
x = someThing[--i];
// do stuff
}

or

var i=someThing.length;
var x;
while ( i-- ) {
x = someThing[i];
// do stuff
}

But it iterates through the elements of someThing backwards (which
often is not a problem, but may be if order is important).

Anyhow, there are a thousand variations on the theme, have a read here:

<URL:http://www.websiteoptimization.com/speed/10/10-2.html>

There is a bug in the page, so download it and fix the bug, then run it
(there's a form and a function called 'testLoop').

Also try here:

<URL:http://4umi.com/web/javascript/optimize.htm>

>
> There is one other way that the do..while loop gives a massive speed boost
> though:
>
> if any of the array elements have non-true values the while loop will exit
> when it hits the first one whereas the for loop will continue through the
> whole array. Obviously aborting the loop after a single iteration instead
> of 10,000 would give a noticeable difference. :^)


Not necessarily, they will only exit early if the value of the element
is (part of) the test, e.g.:

while(someThing[++i]) or while(( x=someThing[--i] ))

or similar. But there are plenty of ways to avoid that, e.g. the first
two while loops proposed above will iterate over every element.



--
Rob
 
Reply With Quote
 
dhplank
Guest
Posts: n/a
 
      06-06-2005
Thanks to everyone for the many helpful hints. After reading throught
the hints and performing various tests, I've been able to establish
that the biggest part of the performance problem has to do with how
Mozilla and Internet Explorer handle DOM (Document Object Module)
obects.

For example, the following bit of code:

<CODE>
for (i=1; i <= 366; i++) {

if ((document.saisir["cal_yr1_type_jour_" + i].value != 35) ||
(document.saisir["cal_yr1_active_jour_" + i].value == 0)) {

document.saisir["cal_yr1_active_jour_" + i].value = 0;
document.saisir["cal_yr1_type_jour_" + i].value = 0;
document.saisir["cal_yr1_debut_jour_" + i].value = 0;
document.saisir["cal_yr1_fin_jour_" + i].value = 0;
document.saisir["cal_yr1_theor_jour_" + i].value = 0;
}
if ((document.saisir["cal_yr2_type_jour_" + i].value != 35) ||
(document.saisir["cal_yr2_active_jour_" + i].value == 0)) {
document.saisir["cal_yr2_active_jour_" + i].value = 0;
document.saisir["cal_yr2_type_jour_" + i].value = 0;
document.saisir["cal_yr2_debut_jour_" + i].value = 0;
document.saisir["cal_yr2_fin_jour_" + i].value = 0;
document.saisir["cal_yr2_theor_jour_" + i].value = 0;
}
}
</CODE>

takes 3.8 seconds under Mozilla, but 36 seconds under Internet
Explorer. And in other cases I've found that Mozilla is as much as 100
times faster than Internet Explorer.

In some cases I've been able to better performance by assigning a DOM
object to a variable which I then re-use. However in a case like the
above this doesn't seem possible (since each object is only used once).

Anyone have any ideas?

 
Reply With Quote
 
Grant Wagner
Guest
Posts: n/a
 
      06-06-2005
"dhplank" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Thanks to everyone for the many helpful hints. After reading throught
> the hints and performing various tests, I've been able to establish
> that the biggest part of the performance problem has to do with how
> Mozilla and Internet Explorer handle DOM (Document Object Module)
> obects.
>
> For example, the following bit of code:
>
> <CODE>
> for (i=1; i <= 366; i++) {
>
> if ((document.saisir["cal_yr1_type_jour_" + i].value != 35) ||
> (document.saisir["cal_yr1_active_jour_" + i].value == 0)) {
>
> document.saisir["cal_yr1_active_jour_" + i].value = 0;
> document.saisir["cal_yr1_type_jour_" + i].value = 0;
> document.saisir["cal_yr1_debut_jour_" + i].value = 0;
> document.saisir["cal_yr1_fin_jour_" + i].value = 0;
> document.saisir["cal_yr1_theor_jour_" + i].value = 0;
> }
> if ((document.saisir["cal_yr2_type_jour_" + i].value != 35) ||
> (document.saisir["cal_yr2_active_jour_" + i].value == 0)) {
> document.saisir["cal_yr2_active_jour_" + i].value = 0;
> document.saisir["cal_yr2_type_jour_" + i].value = 0;
> document.saisir["cal_yr2_debut_jour_" + i].value = 0;
> document.saisir["cal_yr2_fin_jour_" + i].value = 0;
> document.saisir["cal_yr2_theor_jour_" + i].value = 0;
> }
> }
> </CODE>
>
> takes 3.8 seconds under Mozilla, but 36 seconds under Internet
> Explorer. And in other cases I've found that Mozilla is as much as
> 100
> times faster than Internet Explorer.
>
> In some cases I've been able to better performance by assigning a DOM
> object to a variable which I then re-use. However in a case like the
> above this doesn't seem possible (since each object is only used
> once).
>
> Anyone have any ideas?


Yes, take the suggestions that have already been offered and remove all
those accesses to document.forms['saisir'].elements[your_elements],
cache a reference to the elements collection and use it directly. Also
reverse the direction of your loop (not that it makes much difference,
but when dealing with UI, every millisecond counts):

var f = document;
if (f && (f = f.forms) && (f = f['saisir']) && (f = f.elements)) {
for (var i = 367; i-- > 0 {
if (f["cal_yr1_type_jour_" + i].value != 35 || /* etc */) {
f["cal_yr1_active_jour_" + i].value = 0;
// etc
}
}
}

--
Grant Wagner <(E-Mail Removed)>
comp.lang.javascript FAQ - http://jibbering.com/faq


 
Reply With Quote
 
dhplank
Guest
Posts: n/a
 
      06-09-2005
>> Yes, take the suggestions that have already been offered and remove all
those accesses to document.forms['saisir'].elements[your_elements],
cache a reference to the elements collection and use it directly. <<

By taking into account all the suggestions offered, I've managed to
dramatically improve performance. Most transactions now take less than
one second, which is acceptable in the context. Caching the DOM
references is what really speeded things up. I found though that I
have to cache each reference, not just a reference to the form, in
order to get significant improvements.

This means though that I still have one bit of code, which is used to
initialize the page, which is rather slow - it takes about 36 seconds
under Internet Explorer (and only 3 seconds under Mozilla). This bit
of code will only be executed one time per session, so perhaps I can
live with it, but it would be nice to speed it up if at all possible.
Here it is:

<code>

BeginBench();

// Cache DOM values for reuse.
for (i=366; i >= 1; i--) {
c1ac[i] = document.saisir["cal_yr1_active_jour_" + i];
c1ty[i] = document.saisir["cal_yr1_type_jour_" + i];
c1de[i] = document.saisir["cal_yr1_debut_jour_" + i];
c1fi[i] = document.saisir["cal_yr1_fin_jour_" + i];
c1th[i] = document.saisir["cal_yr1_theor_jour_" + i];

c2ac[i] = document.saisir["cal_yr2_active_jour_" + i];
c2ty[i] = document.saisir["cal_yr2_type_jour_" + i];
c2de[i] = document.saisir["cal_yr2_debut_jour_" + i];
c2fi[i] = document.saisir["cal_yr2_fin_jour_" + i];
c2th[i] = document.saisir["cal_yr2_theor_jour_" + i];
}

EndBench("InitRules3");

</code>

(By the way, the DoBench and EndBench subroutines are just used to time
the code.)

I need to work with the hidden "input" fields in the HTML form, as the
whole form is later sent to a parser which recovers everything and
inserts it into a database. I don't think it's feasible to change the
design approach - too much other code is involve.

So ... any ideas on how to reduce the initialization time of this loop,
or am I just stuck with it (get or take a few milliseconds)? Would
getting rid of the loop significantly speed things up? (I might try
that to see.)

 
Reply With Quote
 
Dr John Stockton
Guest
Posts: n/a
 
      06-09-2005
JRS: In article <(E-Mail Removed). com>,
dated Thu, 9 Jun 2005 02:51:10, seen in news:comp.lang.javascript,
dhplank <(E-Mail Removed)> posted :


> // Cache DOM values for reuse.
> for (i=366; i >= 1; i--) {
> c1ac[i] = document.saisir["cal_yr1_active_jour_" + i];
> c1ty[i] = document.saisir["cal_yr1_type_jour_" + i];
> c1de[i] = document.saisir["cal_yr1_debut_jour_" + i];
> c1fi[i] = document.saisir["cal_yr1_fin_jour_" + i];
> c1th[i] = document.saisir["cal_yr1_theor_jour_" + i];
>
> c2ac[i] = document.saisir["cal_yr2_active_jour_" + i];
> c2ty[i] = document.saisir["cal_yr2_type_jour_" + i];
> c2de[i] = document.saisir["cal_yr2_debut_jour_" + i];
> c2fi[i] = document.saisir["cal_yr2_fin_jour_" + i];
> c2th[i] = document.saisir["cal_yr2_theor_jour_" + i];
> }



>So ... any ideas on how to reduce the initialization time of this loop,
>or am I just stuck with it (get or take a few milliseconds)? Would
>getting rid of the loop significantly speed things up? (I might try
>that to see.)



Your document.saisir must be an [array] Object; that code must look
up saisir in document (and there's no doubt a lot there) 3660
times. Try
It = document.saisir
....
c1ac[i] = It["cal_yr1_active_jour_" + i];
which should help.

AIUI, i=366 ; do { ... } while (--i) could be a *little* faster.


You create elements in 10 arrays; it **could** be better, or worse, to
use one array, loaded with a ten-item object - later instead of
clth[i] you'd write A[i].clth .


You're doing calendar work, AIUI. BE SURE, if you are using Date
Objects repeatedly, to do your calendar in UTC rather than in local
time; if your systems are anything like mine, UTC is several times
faster IIRC. Read my site. Also, date objects may not be particularly
fast in comparison with efficient coding (e.g. for month-length); read
my site.

--
John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4
<URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
 
Reply With Quote
 
Thomas 'PointedEars' Lahn
Guest
Posts: n/a
 
      06-10-2005
dhplank wrote:

Please provide proper attribution.
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
>>> Yes, take the suggestions that have already been offered and remove all

> those accesses to document.forms['saisir'].elements[your_elements],
> cache a reference to the elements collection and use it directly. <<


Please learn how to quote in Usenet. `>>'...`<<' is not a widely accepted
quotation style, for one part that it confuses parsers designed to
recognize levels of quotation by one more leading character (usually `>')
and thus allow user agents to format the levels differently.

<http://jibbering.com/faq/faq_notes/pots1.html>

> [...] Caching the DOM references is what really speeded things up.
> I found though that I have to cache each reference, not just a reference
> to the form, in order to get significant improvements.
>
> This means though that I still have one bit of code, which is used to
> initialize the page, which is rather slow - it takes about 36 seconds
> under Internet Explorer (and only 3 seconds under Mozilla). [...]
>
> <code>
>
> BeginBench();
>
> // Cache DOM values for reuse.
> for (i=366; i >= 1; i--) {
> c1ac[i] = document.saisir["cal_yr1_active_jour_" + i];
> c1ty[i] = document.saisir["cal_yr1_type_jour_" + i];
> c1de[i] = document.saisir["cal_yr1_debut_jour_" + i];
> c1fi[i] = document.saisir["cal_yr1_fin_jour_" + i];
> c1th[i] = document.saisir["cal_yr1_theor_jour_" + i];
>
> c2ac[i] = document.saisir["cal_yr2_active_jour_" + i];
> c2ty[i] = document.saisir["cal_yr2_type_jour_" + i];
> c2de[i] = document.saisir["cal_yr2_debut_jour_" + i];
> c2fi[i] = document.saisir["cal_yr2_fin_jour_" + i];
> c2th[i] = document.saisir["cal_yr2_theor_jour_" + i];
> }


IMHO this is just the wrong way of "caching". You are simply "caching"
the DOM tree's "leaf" object's references into objects of built-in type,
however the lookups remain (if not increased) as well as the memory usage
does. It take it that you are trying to access a HTML form. So a
reasonable change of the original code would be to assign a (both standards
compliant and downwards compatible) reference to the HTMLFormElement object
(or its `elements' collection as you can see below) to a variable and use
that variable instead. And I sincerely doubt that you need all references
to be "cached" in an array.

`document.saisir' which should be `document.forms["saisir"] is accessed
very often and you are only accessing the form's elements. So:

// Remove redundancies and use proper references
var es = document.forms["saisir"].elements;
for (i=1; i <= 366; i++)
{
if (es["cal_yr1_type_jour_" + i].value) != 35
|| es["cal_yr1_active_jour_" + i] == 0)
{
es["cal_yr1_active_jour_" + i].value = 0;
es["cal_yr1_type_jour_" + i].value = 0;
es["cal_yr1_debut_jour_" + i].value = 0;
es["cal_yr1_fin_jour_" + i].value = 0;
es["cal_yr1_theor_jour_" + i].value = 0;
}

if (es["cal_yr2_type_jour_" + i].value != 35
|| es["cal_yr2_active_jour_" + i].value == 0)
{
es["cal_yr2_active_jour_" + i].value = 0;
es["cal_yr2_type_jour_" + i].value = 0;
es["cal_yr2_debut_jour_" + i].value = 0;
es["cal_yr2_fin_jour_" + i].value = 0;
es["cal_yr2_theor_jour_" + i].value = 0;
}
}

// Introduce proper scoping and optimize loop
for (var es = document.forms["saisir"].elements, i = 367;
--i // 0 evaluates to `false' in a boolean expression
{
if (es["cal_yr1_type_jour_" + i].value) != 35
|| !es["cal_yr1_active_jour_" + i].value) // !0==true, !!0==false
{
es["cal_yr1_active_jour_" + i].value =
es["cal_yr1_type_jour_" + i].value =
es["cal_yr1_debut_jour_" + i].value =
es["cal_yr1_fin_jour_" + i].value =
es["cal_yr1_theor_jour_" + i].value = 0; // x=0; y=0; <=> x = y= 0;
}

if (es["cal_yr2_type_jour_" + i].value != 35
|| !es["cal_yr2_active_jour_" + i].value)
{
es["cal_yr2_active_jour_" + i].value =
es["cal_yr2_type_jour_" + i].value =
es["cal_yr2_debut_jour_" + i].value =
es["cal_yr2_fin_jour_" + i].value =
es["cal_yr2_theor_jour_" + i].value = 0;
}
}

Optional optimization steps are

for (var es = document.forms["saisir"].elements, i = 367;
--i // 0 evaluates to `false' in a boolean expression
{
for (var j = 3; --j
{
var
cal = "cal_yr" + j,
cal_type_jour = cal + "_type_jour_" + i,
cal_active_jour = cal + "_active_jour_" + i;

if (es[cal_type_jour].value) != 35
|| !es[cal_active_jour].value) // !0==true, !!0==false
{
es[cal_active_jour].value =
es[cal_type_jour].value =
es[cal + "_debut_jour_" + i].value =
es[cal + "_fin_jour_" + i].value =
es[cal + "_theor_jour_" + i].value = 0; // x=0; y=0; <=> x = y= 0;
}
}
}

and so on.

The above code is probably triggered by an event. If yes, the even listener
should include a reference to the object that caused the event. E.g. if
the above code is executed in a method named `setZero', it could be changed
as follows:

<script type="text/javascript">
function setZero(o)
{
if ((o = o.form))
{
var e = o.elements;
// ...
}
}
}
</script>
...
<form ...>
...
<script type="text/javascript">
document.write('<input type="button" onclick="setZero(this);">');
</script>
...
</form>

Thus the form element's name does not matter anymore and two more lookups
per each loop are saved.

Further optimization can be done by having the elements have the same name.
Thus in the DOM an elements collection (an HTMLCollection object in a
standards compliant implementation) is created which removes the need for
concatenating the `i' value and for the hard-coded maximum index as it then
can be obtained reading the `length' property of that collection (where
indexes would be 0-based then). This would probably require a minor
redesign of the server-side application, though. For server-side PHP,
names ending with `[]' should be used as they become accessible as arrays
instead of plain values server-side then.

I am not sure where the `35' comes from, however this should not be
hardcoded (at least not repeatedly) as well. This change would decrease
performance a little bit (since it introduces a scope chain resolution
process), but would reduce future maintenance costs.

(And if `0' is the default value and there are no other elements (probably
the hidden `input' elements are not required), the entire script can
probably be replaced with <input type="reset" ...>.)

> I need to work with the hidden "input" fields in the HTML form, as the
> whole form is later sent to a parser which recovers everything and
> inserts it into a database.


It is not the parser, really.

> I don't think it's feasible to change the design approach - too much
> other code is involve.


Depending on what you mean with `design approach', you may or may not
have to accept that this will keep client-side processing slower than
it could be.

I wonder why you find it necessary to set the values to `0'; why do
you not use `<input type="hidden" ... value="0">'?

Furthermore, it appears that you do not take into account that there
are UAs out there where client-side scripting is unavailable and so
you have to provide a viable alternative.

> So ... any ideas on how to reduce the initialization time of this loop,
> or am I just stuck with it (get or take a few milliseconds)? Would
> getting rid of the loop significantly speed things up? (I might try
> that to see.)


Yes, it would of course, but it would possibly also remove a feature.
You are to decide whether that is acceptable or not, depending on the
reply you would give to the comment right above.


HTH

PointedEars
--
Bill Gates isn't the devil -- Satan made sure hell
_worked_ before he opened it to the damned ...
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FASTER THAN ANTICIPATED TRANSITIONS IN THE INTERNET AC Java 1 05-10-2011 05:32 PM
Internet Explorer 8: C:\Program Files\Internet Explorer\iexplore.exe vs C:\Program Files (x86)\Internet Explorer\iexplore.exe Nathan Sokalski Windows 64bit 16 02-22-2010 08:31 AM
internet explorer 7 - Internet Explorer cannot display the webpag sandy j Windows 64bit 0 05-02-2009 02:12 AM
Mozilla is better than firefox. Hail to Mozilla. Death to firefox. Radium Firefox 29 03-27-2007 02:51 AM
Internet connections faster than a cable modem Bradley Burton Computer Information 2 04-06-2004 03:29 PM



Advertisments