<select>.remove() Performance and Necessity

R

Richard Maher

Hi,

I have read many of the copius entries on the subject of IE performance (or
the lack thereof) when populating Select Lists.

I don't mind the insert performance so much, (I get 100x120byte rows
inserted/sec up to 500, and 100rows/6secs up to 3000, which isn't great but
then the Row Count is clicking away for the user to see and they can hit the
"cancel" button at anytime, so overall I'm happy), what really disappoints
me is the woeful of .REMOVE()!

Before fetching the next result-set I clear down the existing options (I
*do* have to do this don't I?) by looping through option collection calling
remove(1). (Would it be quicker if I removed the last option? Option[0] is a
header.) For 3000 rows this takes an unbelievable 20+secs :-( Does this
sound about right?

1) Is it only IE that performs badly on this?
2) Is there a quicker or more efficient way of zeroing the Select List?
2a) The w3schools ref says the "length" attribute "Returns the number of
options in a dropdown list" it doesn't say "sets Or returns"
2b) The French guy (Stephane?) suggested that I should just set the length
to zero, but wouldn't that result in a memory leak?
3) Do I need to create a malloc/realloc function that keeps a high-water
mark of available option objects for this Drop Down and only "new" some more
options when that's exceeded? (But then the Length would always be off)
4) Use tables and not select lists?
5) Use another browser

Cheers Richard Maher

PS. I changed the .sort(myCompare) from removing/adding to just changing the
..TEXT value and it went from 30secs/3000 rows to ~1sec!
 
R

RobG

Richard said:
Hi,

I have read many of the copius entries on the subject of IE performance (or
the lack thereof) when populating Select Lists.

I don't mind the insert performance so much, (I get 100x120byte rows
inserted/sec up to 500, and 100rows/6secs up to 3000, which isn't great but
then the Row Count is clicking away for the user to see and they can hit the
"cancel" button at anytime, so overall I'm happy), what really disappoints
me is the woeful of .REMOVE()!

Are you talking about a select element or a table?

Before fetching the next result-set I clear down the existing options (I
*do* have to do this don't I?) by looping through option collection calling
remove(1). (Would it be quicker if I removed the last option? Option[0] is a
header.) For 3000 rows this takes an unbelievable 20+secs :-( Does this
sound about right?

To remove all the options in one go, set the select element's
options.length attribute to zero.

1) Is it only IE that performs badly on this?

Badly at what? Probably the fastest and most cross-browser method to
create option elements is to use:

select.options = new Option(optText, optValue);

2) Is there a quicker or more efficient way of zeroing the Select List?

Set the options collection's length property to zero.

2a) The w3schools ref says the "length" attribute "Returns the number of
options in a dropdown list" it doesn't say "sets Or returns"

w3schools is an OK introduction to javascript, but it is not an
authority and has many errors and instances of bad advice. Read the W3C
specification:

"length of type unsigned long
"This attribute specifies the length or size of the list."

<URL:
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection >

2b) The French guy (Stephane?) suggested that I should just set the length
to zero, but wouldn't that result in a memory leak?

Why would it result in a memory leak?

3) Do I need to create a malloc/realloc function that keeps a high-water
mark of available option objects for this Drop Down and only "new" some more
options when that's exceeded? (But then the Length would always be off)

While I don't know what malloc/realloc means to you, but regardless,
there's no such equivalent in javascript. There are no specific
mechanisms for controlling memory allocation.

4) Use tables and not select lists?

They are totally different things.

5) Use another browser

?
 
R

Richard Maher

Hi Rob,

Thanks for the reply.
Are you talking about a select element or a table?

Select Element.
To remove all the options in one go, set the select element's
options.length attribute to zero.
: : :
Set the options collection's length property to zero.
: : :
Why would it result in a memory leak?

Why would all of the New Option objects that were instantiated during the
load of the select list suddenly disappear and have their memory freed up by
setting the array length to zero? Maybe it doesn't, but the space/elements
get re-used next time round?

Anyway, I'll take your (and Stephane's) advice and just shrink the array
length. Thanks.

I guess the remove() method is there for when surgical strikes are called
for?
Badly at what? Probably the fastest and most cross-browser method to
create option elements is to use:

select.options = new Option(optText, optValue);


Yep, that's what I'm doing (I'll have to stick in the 2nd parameter to be
x-browser safe) and I'm getting the performance I described for inserts. It
was specifically the REMOVE performance that was giving me grief.

Cheers Richard Maher

RobG said:
Richard said:
Hi,

I have read many of the copius entries on the subject of IE performance (or
the lack thereof) when populating Select Lists.

I don't mind the insert performance so much, (I get 100x120byte rows
inserted/sec up to 500, and 100rows/6secs up to 3000, which isn't great but
then the Row Count is clicking away for the user to see and they can hit the
"cancel" button at anytime, so overall I'm happy), what really disappoints
me is the woeful of .REMOVE()!

Are you talking about a select element or a table?

Before fetching the next result-set I clear down the existing options (I
*do* have to do this don't I?) by looping through option collection calling
remove(1). (Would it be quicker if I removed the last option? Option[0] is a
header.) For 3000 rows this takes an unbelievable 20+secs :-( Does this
sound about right?

To remove all the options in one go, set the select element's
options.length attribute to zero.

1) Is it only IE that performs badly on this?

Badly at what? Probably the fastest and most cross-browser method to
create option elements is to use:

select.options = new Option(optText, optValue);

2) Is there a quicker or more efficient way of zeroing the Select List?

Set the options collection's length property to zero.

2a) The w3schools ref says the "length" attribute "Returns the number of
options in a dropdown list" it doesn't say "sets Or returns"

w3schools is an OK introduction to javascript, but it is not an
authority and has many errors and instances of bad advice. Read the W3C
specification:

"length of type unsigned long
"This attribute specifies the length or size of the list."

<URL:
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection >

2b) The French guy (Stephane?) suggested that I should just set the length
to zero, but wouldn't that result in a memory leak?

Why would it result in a memory leak?

3) Do I need to create a malloc/realloc function that keeps a high-water
mark of available option objects for this Drop Down and only "new" some more
options when that's exceeded? (But then the Length would always be off)

While I don't know what malloc/realloc means to you, but regardless,
there's no such equivalent in javascript. There are no specific
mechanisms for controlling memory allocation.

4) Use tables and not select lists?

They are totally different things.

5) Use another browser

?
 
R

Richard Maher

Hi Again,
Anyway, I'll take your (and Stephane's) advice and just shrink the array
length. Thanks.

Ok I did that and I'm now more confident that there won't be a memory leak
'cos the performance is still as crap as when I was explicitly calling
..remove()

If I currently have 3000x120byte rows in the selectList then it takes
~24secs to set the length to zero (or to "one" in my case with a "header"
row) before it starts re-populating the select list with the next result
set. (And then about 1min10secs to repopulate it)

Can someone manage my expectations here on what "reasonable" performance
should be with Select Lists?

The strange (at least to me) thing is that is CPU bound and doesn't appear
to be a memory issue at all. The page shows 100% cpu while it's deallocating
and then a short break until the server has primed the socket with data and
then it's 100% straight until the last row is inserted. Memory usage doesn't
seen to budge. (That's a shit load of CPU for the Mickey Mouse work we're
talking about!)

This has gotta be pilot error surely? Are there some obvious IE or Windows
tuning parameters that I should look at?

Once again, I am setTimeout(getNextRecord,0) as a loop control so that the
Record Count clicks over and the screen gets updated. But clearly that
shouldn't effect the "Free" processing. I'll give it a go at setting the
length to zero instead of one to see if that makes a difference.

Cheers Richard Maher

BTW. It's a Pentium 1300MHz Laptop running Windows2000 and IE6


Richard Maher said:
Hi Rob,

Thanks for the reply.
Are you talking about a select element or a table?

Select Element.
To remove all the options in one go, set the select element's
options.length attribute to zero.
: : :
Set the options collection's length property to zero.
: : :
Why would it result in a memory leak?

Why would all of the New Option objects that were instantiated during the
load of the select list suddenly disappear and have their memory freed up by
setting the array length to zero? Maybe it doesn't, but the space/elements
get re-used next time round?

Anyway, I'll take your (and Stephane's) advice and just shrink the array
length. Thanks.

I guess the remove() method is there for when surgical strikes are called
for?
Badly at what? Probably the fastest and most cross-browser method to
create option elements is to use:

select.options = new Option(optText, optValue);


Yep, that's what I'm doing (I'll have to stick in the 2nd parameter to be
x-browser safe) and I'm getting the performance I described for inserts. It
was specifically the REMOVE performance that was giving me grief.

Cheers Richard Maher

performance
great
hit
the

Are you talking about a select element or a table?
Option[0]
is a
header.) For 3000 rows this takes an unbelievable 20+secs :-( Does this
sound about right?

To remove all the options in one go, set the select element's
options.length attribute to zero.

1) Is it only IE that performs badly on this?

Badly at what? Probably the fastest and most cross-browser method to
create option elements is to use:

select.options = new Option(optText, optValue);

2) Is there a quicker or more efficient way of zeroing the Select
List?

Set the options collection's length property to zero.

2a) The w3schools ref says the "length" attribute "Returns the number of
options in a dropdown list" it doesn't say "sets Or returns"

w3schools is an OK introduction to javascript, but it is not an
authority and has many errors and instances of bad advice. Read the W3C
specification:

"length of type unsigned long
"This attribute specifies the length or size of the list."

<URL:
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#HTMLOptionsCollection >

2b) The French guy (Stephane?) suggested that I should just set the length
to zero, but wouldn't that result in a memory leak?

Why would it result in a memory leak?

3) Do I need to create a malloc/realloc function that keeps a high-water
mark of available option objects for this Drop Down and only "new"
some
more off)

While I don't know what malloc/realloc means to you, but regardless,
there's no such equivalent in javascript. There are no specific
mechanisms for controlling memory allocation.



They are totally different things.



?
 
R

RobG

Hi Again,

Please trim the bits you aren't replying to.

Ok I did that and I'm now more confident that there won't be a memory leak
'cos the performance is still as crap as when I was explicitly calling
.remove()

If I currently have 3000x120byte rows in the selectList then it takes

You mean 3,000 option elements? Do you really want to do that?
~24secs to set the length to zero (or to "one" in my case with a "header"
row) before it starts re-populating the select list with the next result
set. (And then about 1min10secs to repopulate it)

I can't test IE right now, but for a select with 3,000 options,
setting options.length = 0 in Safari takes about 320ms, Firefox 120ms,
Opera 160ms on an iBook 2GHz Core2Duo. Some test code is below.

Can someone manage my expectations here on what "reasonable" performance
should be with Select Lists?

Adding 3,000 options takes Safari 750ms, Firefox 220ms and Opera
530ms.
The strange (at least to me) thing is that is CPU bound and doesn't appear
to be a memory issue at all. The page shows 100% cpu while it's deallocating
and then a short break until the server has primed the socket with data and
then it's 100% straight until the last row is inserted. Memory usage doesn't
seen to budge. (That's a shit load of CPU for the Mickey Mouse work we're
talking about!)

Ask MS to fix their browser.
This has gotta be pilot error surely? Are there some obvious IE or Windows
tuning parameters that I should look at?

Ditch IE?


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<title>Options play</title>
<script type="text/javascript">

function removeOptions(f){
var s = new Date();
f.sel0.options.length = 0;
document.getElementById('xx').innerHTML = (new Date() - s)+'ms';
}

function addOptions(f){
var sel = f.sel0;
var s = new Date();
for (var i=0; i<3000; i++) {
sel.options = new Option(i, i);
}
document.getElementById('xx').innerHTML = (new Date() - s)+'ms';
}

</script>

<form name="country"><div>
<input type="button" onclick="removeOptions(this.form)"
value="Remove options">
<input type="button" onclick="addOptions(this.form)"
value="Add options"><br>
<select name="sel0">
<script type="text/javascript">
var t = [];
for (var i=0; i<3000; i++){
t.push('<option>' + i);
}
document.write(t.join(''));
</script>
</select>
</div></form>
<div>Time taken: <span id="xx"></span></div>
 
R

RobG

On Apr 27, 4:18 pm, "Richard Maher" <[email protected]> [...]
This has gotta be pilot error surely? Are there some obvious IE or Windows
tuning parameters that I should look at?

Ditch IE?

Something you might try is replacing the select with a shallow clone
of itself - test widely, it may not be well supported by older
browsers:

function removeOptions2(f){
var sel = f.elements['sel0'];
var oSel = sel.cloneNode(false);
oSel.options[0] = new Option('New option');
sel.parentNode.replaceChild(oSel, sel);
}


Note that a select with no options is invalid HTML. Times in browses
reported previously are: 57ms, 14ms and 7ms respectively.
 
R

Richard Maher

Hi Rob
You mean 3,000 option elements? Do you really want to do that?

I have only recently stumbled across the school of thought that says
JavaScript and HTML are more than capable of providing the functionality and
performance needed for a complete browser-based application GUI, so I
thought it was time that I educated myself a little bit about the potential
of these tools. To that end I've built a proof-of-concept example, one part
of which is the loading a database-query result-set into a scrolling list.
Now, I imagine 99% of the time we'd be talking 10s to low 100s of matching
rows, but I don't think 3000 is ridiculous or out of the realms of
possibility. (Especially as the user is empowered (by the hot abort button)
to terminate the query at any time, if they so choose. The "All transactions
between a certain date range" scenario.)
Adding 3,000 options takes Safari 750ms, Firefox 220ms and Opera
530ms.

Thanks for the example code and real figures. I know I should've done that.

Your code on my box takes 20910ms to add 3K and 4907ms to remove them :-(

The second and subsequent times the "add" consistently took ~5600ms and the
"remove" stayed at 4860ms.

Does anyone else have IE7 that they can run Rob's code on to check?
Ask MS to fix their browser.
: : : :
Ditch IE?

Certainly looks the way to go. What could it possibly be doing with all that
CPU? Bitmap or hash algorithm for *every* free byte in memory?

Ok, going forward, can I run FireFox on my Windows2000 box and have it
co-exists happily with IE? (IE in one window, FF in another?)

Cheers Richard Maher
 
R

Richard Maher

Rob G you are an absolute bloody champion!
Something you might try is replacing the select with a shallow clone
of itself - test widely, it may not be well supported by older
browsers:

function removeOptions2(f){
var sel = f.elements['sel0'];
var oSel = sel.cloneNode(false);
oSel.options[0] = new Option('New option');
sel.parentNode.replaceChild(oSel, sel);
}

20ms is all it takes (Now I have to see if I can get it to work with my
code. "Why should it be any different?" you ask, well maybe I'm just being a
worry wart but I've had sooo much trouble with turning off selectedIndex and
then if there's only one option (my header row) then sometimes it's blank
and then you click the down arrow the option appears there, and flickering,
and I've left the size at 2 for another select list even if the length is
only 1 just so it doesn't stuff up the screen and and and who cares?)

Given the problem statement you played a blinder! Thanks again.

Cheers Richard Maher

PS. Where does one find the documentation for all these replaceChild and
appendChild methods?

RobG said:
On Apr 27, 4:18 pm, "Richard Maher" <[email protected]> [...]
This has gotta be pilot error surely? Are there some obvious IE or Windows
tuning parameters that I should look at?

Ditch IE?

Something you might try is replacing the select with a shallow clone
of itself - test widely, it may not be well supported by older
browsers:

function removeOptions2(f){
var sel = f.elements['sel0'];
var oSel = sel.cloneNode(false);
oSel.options[0] = new Option('New option');
sel.parentNode.replaceChild(oSel, sel);
}


Note that a select with no options is invalid HTML. Times in browses
reported previously are: 57ms, 14ms and 7ms respectively.
 
R

Richard Maher

Hi,

Thanks for the references.
["scripts.contact" Gave me several usefule web references]

Related to Rob's solution of a shallow clone of the SelectList node, can
someone advise me of a better way to preserve the "header" row(s) contents
and attributes across versions of the Select Nodes? This is what I'm doing
now: -

selectRef.size = 1;
selectClone = selectRef.cloneNode(false);
lovHdr = document.getElementById('lovHdr');
hdrClone = lovHdr.cloneNode(true);
selectClone.appendChild(hdrClone);
selectRef.parentNode.replaceChild(selectClone, selectRef);
selectRef = document.getJobs.jobList;

I could (like Rob's example) just recreate the header entry each time with a
"new Option ('my header')" but I was rather hoping to just have a template
Node (for a blank SelectList with nothing but its option[0] header and all
its child nodes) sitting there that could be redeployed when needed.

Am I correct in thinking that each clone is consumed by the replaceChild()
so the cloneNode() has to happen anyway? And if I try to create a clone at
page-load time (then do a clone of that clone at replace-time) then I'm
going to run into trouble with ElementIds between the real selectList and
the dummy-template clone?

Anyway, who cares? I like it the way it is. Thanks again for the help - the
performance is great!

Cheers Richard Maher
 
R

RobG


Please don't top-post, reply below trimmed quotes.

Thanks for the references.
["scripts.contact" Gave me several usefule web references]

Related to Rob's solution of a shallow clone of the SelectList node, can
someone advise me of a better way to preserve the "header" row(s) contents
and attributes across versions of the Select Nodes? This is what I'm doing
now: -

selectRef.size = 1;
selectClone = selectRef.cloneNode(false);
lovHdr = document.getElementById('lovHdr');
hdrClone = lovHdr.cloneNode(true);
selectClone.appendChild(hdrClone);

The above two lines could be:

selectClone.appendChild(lovHdr.cloneNode(true));

selectRef.parentNode.replaceChild(selectClone, selectRef);
selectRef = document.getJobs.jobList;

I could (like Rob's example) just recreate the header entry each time with a
"new Option ('my header')" but I was rather hoping to just have a template
Node (for a blank SelectList with nothing but its option[0] header and all
its child nodes) sitting there that could be redeployed when needed.

Why just clone the option? Why not clone the whole "template" select,
modify the attribute appropriately and replace the one that's there?

Am I correct in thinking that each clone is consumed by the replaceChild()
so the cloneNode() has to happen anyway?

Consumed? When you clone an element, you create a new object. If you
want to have say six new objects (in this case, DOM HTML select
elements), you have to make six clones.
And if I try to create a clone at
page-load time (then do a clone of that clone at replace-time) then I'm
going to run into trouble with ElementIds between the real selectList and
the dummy-template clone?

As long as the template clone isn't added to the DOM (say using
appendChild) you're OK. document.getElementById only searches the
DOM, it has no idea what you are holding references to elsewhere (or
at least it shouldn't - if it does it's a bug).

A simple test:

<div id="xx"></div>

<script type="text/javascript">
var x = document.getElementById('xx');
var y = x.cloneNode(true);
x.parentNode.removeChild(x);
alert(document.getElementById('xx') +
'\n' + y + ' id: ' + y.id);
</script>

In IE and Firefox, div xx is removed from the document, getElementById
can't find the clone.
 
R

Richard Maher

Hi Rob,
As long as the template clone isn't added to the DOM (say using
appendChild) you're OK. document.getElementById only searches the
DOM, it has no idea what you are holding references to elsewhere (or
at least it shouldn't - if it does it's a bug).

That's the bit I wasn't sure of. Sounds great; I'll give it a go.

Cheers Richard Maher
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top