Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Removing all children from an element

2 views
Skip to first unread message

Tim Streater

unread,
Mar 13, 2009, 5:47:01 PM3/13/09
to
To remove all children from an element, does it work just to set the
childNodes array length to zero, as in:

ptr.childNodes.length = 0;

googling for anything like "remove all child nodes" has everyone
suggesting doing it by removing them one at a time.

Cheers,

--
Tim

"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689

Jeremy J Starcher

unread,
Mar 13, 2009, 5:58:30 PM3/13/09
to
On Fri, 13 Mar 2009 21:47:01 +0000, Tim Streater wrote:

> To remove all children from an element, does it work just to set the
> childNodes array length to zero, as in:
>
> ptr.childNodes.length = 0;

It shouldn't.

The specs for a nodeList. Not that 'length' is identified as readonly.

http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/
core.html#ID-536297177

> googling for anything like "remove all child nodes" has everyone
> suggesting doing it by removing them one at a time.

I have seen another method that involved doing a shallow clone of the
parent node and replacing it, but then existing references to that node
are now invalid


Jeremy J Starcher

unread,
Mar 13, 2009, 6:04:10 PM3/13/09
to
On Fri, 13 Mar 2009 21:47:01 +0000, Tim Streater wrote:

> To remove all children from an element, does it work just to set the
> childNodes array length to zero, as in:
>
> ptr.childNodes.length = 0;

It shouldn't.

The specs for a nodeList. Note that 'length' is identified as readonly.


http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/
core.html#ID-536297177

> googling for anything like "remove all child nodes" has everyone


> suggesting doing it by removing them one at a time.

I have seen another method that involved doing a shallow clone of the


parent node and replacing it, but then existing references to that node

are now invalid.

Tim Streater

unread,
Mar 13, 2009, 6:55:29 PM3/13/09
to
In article <aGAul.1958$im1...@nlpi061.nbdc.sbc.com>,

Jeremy J Starcher <r3...@yahoo.com> wrote:

> On Fri, 13 Mar 2009 21:47:01 +0000, Tim Streater wrote:
>
> > To remove all children from an element, does it work just to set the
> > childNodes array length to zero, as in:
> >
> > ptr.childNodes.length = 0;
>
> It shouldn't.
>
> The specs for a nodeList. Not that 'length' is identified as readonly.

OK - thanks. Unsurprising really given that all the examples said
otherwise.

Jeremy J Starcher

unread,
Mar 13, 2009, 7:08:58 PM3/13/09
to
On Fri, 13 Mar 2009 22:55:29 +0000, Tim Streater wrote:

> In article <aGAul.1958$im1...@nlpi061.nbdc.sbc.com>,
> Jeremy J Starcher <r3...@yahoo.com> wrote:
>> The specs for a nodeList. Not that 'length' is identified as readonly.

^^^ Should be NOTE.

> OK - thanks. Unsurprising really given that all the examples said
> otherwise.

I tried to cancel this message when I spotted that typo. Ah, well.
Figures.

SAM

unread,
Mar 13, 2009, 7:09:18 PM3/13/09
to
Le 3/13/09 10:47 PM, Tim Streater a écrit :

> To remove all children from an element, does it work just to set the
> childNodes array length to zero, as in:
>
> ptr.childNodes.length = 0;

I think : no

> googling for anything like "remove all child nodes" has everyone
> suggesting doing it by removing them one at a time.

Yes, usually it is something like ;
while(ptr.firstChild) ptr.removeChild(ptr.firstChild)
or
while(ptr.hasChildNode()) ptr.removeChild(ptr.firstChild)

Other way (faster) :
var prt1 = prt.cloneNode(false);
prt.parentNode.replaceChild(prt1, prt);


The usual way is interesting when you need to memorize deleted elements
for re-use (undo ?)


<script type="text/javascript">
var mem = [];
function deletOrUndo(id) {
id = document.getElementById(id);
if(id.getElementsByTagName('*').length>0) {
mem = [];
while(id.firstChild) mem[mem.length] = id.removeChild(id.firstChild);
}
else {
var n = mem.length;
while(n--) id.appendChild(mem[n]);
}
}
</script>

<p><button onclick="deletOrUndo('test')">
empty or fill back 'test'</button></p>
<div id="test">
<h2>test</h2>
<p>line 1</p>
<p>line 2</p>
<p>line 3</p>
</div>


--
sm

SAM

unread,
Mar 13, 2009, 7:42:10 PM3/13/09
to
Le 3/14/09 12:09 AM, SAM a écrit :

>
> function deletOrUndo(id) {
> id = document.getElementById(id);
> if(id.getElementsByTagName('*').length>0) {
> mem = [];
> while(id.firstChild) mem[mem.length] = id.removeChild(id.firstChild);
> }

else {
for(var i=0, n = mem.length; n>i; i++) id.appendChild(mem[i]);
}

}


Or :

function deletOrUndo(id) {
id = document.getElementById(id);
if(id.getElementsByTagName('*').length>0) {
mem = [];

while(id.lastChild) mem[mem.length] = id.removeChild(id.lastChild);


}
else {
var n = mem.length;
while(n--) id.appendChild(mem[n]);
}
}


--
sm

Jorge

unread,
Mar 13, 2009, 8:06:57 PM3/13/09
to
On Mar 14, 12:09 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
wrote:

>
> Yes, usually it is something like ;
> while(ptr.firstChild) ptr.removeChild(ptr.firstChild)
> or
> while(ptr.hasChildNode()) ptr.removeChild(ptr.firstChild)
>
> Other way (faster) :
> var prt1 = prt.cloneNode(false);
> prt.parentNode.replaceChild(prt1, prt);
>

Why not a simple .innerHTML= ""; ? It's ~ as fast and less cumbersome.

Their relative speeds : http://jorgechamorro.com/cljs/048/

// innerHTML
function innerHTML () {
fillTheContainer();
container.innerHTML= "";
}

// removeChild
function removeChild () {
var e;
fillTheContainer();
while (e= container.firstChild) {
container.removeChild(e);
}
}

// replaceChild
function replaceChild () {
fillTheContainer();
var newE= container.cloneNode(false);
container.parentNode.replaceChild(newE, container);
container= newE;
}

--
Jorge.

SAM

unread,
Mar 13, 2009, 8:55:57 PM3/13/09
to
Le 3/14/09 1:06 AM, Jorge a écrit :

> On Mar 14, 12:09 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
> wrote:
>> Yes, usually it is something like ;
>> while(ptr.firstChild) ptr.removeChild(ptr.firstChild)
>> or
>> while(ptr.hasChildNode()) ptr.removeChild(ptr.firstChild)
>>
>> Other way (faster) :
>> var prt1 = prt.cloneNode(false);
>> prt.parentNode.replaceChild(prt1, prt);
>>
>
> Why not a simple .innerHTML= ""; ? It's ~ as fast and less cumbersome.

Because I use innerHTML least possible ?

> Their relative speeds : http://jorgechamorro.com/cljs/048/

innerHTML 63
replaceChild 70
removeChild 51

Maybe the test would have been better if the 333 inside divs were not
empty ?

Jorge

unread,
Mar 14, 2009, 7:00:30 AM3/14/09
to
On Mar 14, 1:55 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
wrote:

> > Their relative speeds : http://jorgechamorro.com/cljs/048/
>
> innerHTML       63
> replaceChild    70
> removeChild     51
>
> Maybe the test would have been better if the 333 inside divs were not
> empty ?

They're not being cloned in replaceChild (.cloneNode(false)), and it
takes as long to loop over 333 empty divs as it takes to loop over 333
non-empty divs... Anyway, now there are 666 non-empty <div>(s) and 666
children <p>(s) each containing a text. The results are:


Safari 4.0 on Intel Mac OS X 10_5_6 (debugger off):
innerHTML 664
replaceChild 715
removeChild 92

FF 3.0.7 /Mac (debugger off):
innerHTML 45
replaceChild 62
removeChild 33

Opera 964/Mac (debugger off):
innerHTML 258
replaceChild 232
removeChild 105

Firefox 2.0.0.20 (debugger off):
innerHTML 40
replaceChild 76
removeChild 23

MSIE 6.0 on Windows NT
innerHTML 18
replaceChild 12
removeChild 7

MSIE 7.0 on Windows NT
innerHTML 17
replaceChild 12
removeChild 9

MSIE 8.0 on Windows NT
innerHTML 19
replaceChild 11
removeChild 13

Safari 3.2.2 on Windows NT
innerHTML 352
replaceChild 262
removeChild 242

Chrome 1.0.154.48 on Windows NT
innerHTML 198
replaceChild 166
removeChild 92

Opera 9.64 on Windows NT
innerHTML 109
replaceChild 81
removeChild 67

Firefox 3.0.7 on Windows NT
innerHTML 56
replaceChild 54
removeChild 36

Firefox 3.0.5 on Windows NT
innerHTML 55
replaceChild 38
removeChild 26


You might argue that .innerHTML isn't in the DOM standards (yet), but
XMLHttpRequest isn't either (yet). .innerHTML is a plug to the (highly-
optimized) built-in parser.

Check it out: http://jorgechamorro.com/cljs/048/

var masterContainer= document.createElement('div');
var container= document.body.appendChild(document.createElement
('div'));
var size= 666;

(function fillMasterContainer () {
var n= size;
var txt= "Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur vitae nibh vitae sem fringilla tempus. Pellentesque id quam
ac lorem porttitor viverra. Curabitur nulla ipsum, mattis quis,
sollicitudin et, pulvinar sit amet, quam. Nunc ultricies risus vel
ipsum. Fusce eleifend urna vestibulum sapien. Praesent vehicula, orci
et mattis laoreet, ipsum enim adipiscing augue, at malesuada dolor
justo non dui. Vivamus aliquet, odio vel ullamcorper viverra, ante
mauris tempor enim, eu mollis orci dui et magna. Etiam non mauris ac
libero consectetur mollis. Pellentesque sed purus. Donec semper
consequat augue. Sed purus erat, luctus imperdiet, porttitor at,
feugiat sed, dui. Mauris vel augue eget metus convallis tempor.
Quisque blandit sem ac magna.";
while (n--) {
masterContainer.appendChild(
document.createElement('div')).appendChild(
document.createElement('p')).innerHTML= txt;
}
})();

function fillTheContainer () {
var newContainer= masterContainer.cloneNode(true);
container.parentNode.replaceChild(newContainer, container);
container= newContainer;
}

--
Jorge.

rf

unread,
Mar 14, 2009, 7:15:51 AM3/14/09
to
SAM wrote:

> Because I use innerHTML least possible ?

Why?


Jorge

unread,
Mar 14, 2009, 7:25:55 AM3/14/09
to
On Mar 14, 12:00 pm, Jorge <jo...@jorgechamorro.com> wrote:
> (...) The results are: (...)

>
> MSIE 6.0 on Windows NT
> innerHTML 18
> replaceChild 12
> removeChild 7

Safari 3.1.1 on iPhone OS 2_2
innerHTML 7
replaceChild 8
removeChild 4

--
Jorge.

SAM

unread,
Mar 14, 2009, 11:01:48 AM3/14/09
to
Le 3/14/09 12:15 PM, rf a écrit :

> SAM wrote:
>
>> Because I use innerHTML least possible ?
>
> Why?

Essentialy because :
<http://stephane.moriaux.pagesperso-orange.fr/truc/innerHTML_danger>

--
sm

RobG

unread,
Mar 14, 2009, 11:05:35 AM3/14/09
to
On Mar 14, 9:00 pm, Jorge <jo...@jorgechamorro.com> wrote:
> On Mar 14, 1:55 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
> wrote:
>
> > > Their relative speeds :http://jorgechamorro.com/cljs/048/
>
> > innerHTML       63
> > replaceChild    70
> > removeChild     51
>
> > Maybe the test would have been better if the 333 inside divs were not
> > empty ?
>
> They're not being cloned in replaceChild (.cloneNode(false)), and it
> takes as long to loop over 333 empty divs as it takes to loop over 333
> non-empty divs... Anyway, now there are 666 non-empty <div>(s) and 666
> children <p>(s) each containing a text. The results are:
>
> Safari 4.0 on Intel Mac OS X 10_5_6 (debugger off):
> innerHTML       664
> replaceChild    715
> removeChild     92

Dunno what processor you have, but Safari 4 on a 1GHz G4 iBook gives:

innerHTML 118
replaceChild 139
removeChild 25


Anyhow, I think the test is flawed. The browser should be given time
to actually render the content before it is removed - the results for
iPhone are clearly suspicious.

Also, I usually find doing an assignment in the test expression slows
things down, e.g.


while (e= container.firstChild) {
container.removeChild(e);
}

Is faster written as:

while (container.firstChild)
container.removeChild(container.firstChild)

The innerHTML method has issues as it isn't suitable everywhere - I'd
not like to use it on tables in iE. The cloneNode method has issues
too, because the original "container" is replaced (references to the
original are broken and listeners may or may not be still attached
depending on the browser and how they were attached).

Removing the child nodes is more robust. Even though it's the slowest,
it's still reasonably fast for a few hundred elements so if speed
isn't an issue, use it.

It's the old story of optimise when necessary and chose the right tool
for the job.


Below is some alternative test code, on iPhone it gives:

innerHTML: 50
removeChild (assignment outside condition): 106
removeChild (assignment in condition): 115
byClone: 32

Safari 4 on a 1GHz MacBook G4 gives:

innerHTML: 33
removeChild (assignment outside condition): 46
removeChild (assignment in condition): 85
byClone: 4

Firefox 3 on the same MacBook gives:

innerHTML: 37
removeChild (assignment outside condition): 129
removeChild (assignment in condition): 104
byClone: 9


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

function iHTML(el) {
el.innerHTML = ''
};

function rChild0(el) {
while (el.firstChild)
el.removeChild(el.firstChild);
}

function rChild1(el) {
var e;
while (e = el.firstChild)
el.removeChild(e);
}

function byClone(el) {
var el2 = el.cloneNode(false);
el.parentNode.replaceChild(el2, el);
}

window.onload = function() {

var msg = [], s, f;

s = new Date();
iHTML(document.getElementById('d0'));
f = new Date();
msg.push('innerHTML: ' + (f - s));

s = new Date();
rChild0(document.getElementById('d1'));
f = new Date();
msg.push('removeChild ' +
'(assignment outside condition): ' + (f - s));

s = new Date();
rChild1(document.getElementById('d2'));
f = new Date();
msg.push('removeChild ' +
'(assignment in condition): ' + (f - s));

s = new Date();
byClone(document.getElementById('d3'));
f = new Date();
msg.push('byClone: ' + (f - s));

alert(msg.join('\n'));
}
</script>

<script type="text/javascript">
var html = [];
var i = 4,
j,
n = 600;

while(i--) {
j = n;
html.push('<div id="d' + i + '">');

while (j--) {
html.push('<p>Ipsum lorem ' + i + '</p>');
}
html.push('</div>');
}
document.write(html.join(''));
</script>

</body>


--
Rob

rf

unread,
Mar 14, 2009, 5:34:09 PM3/14/09
to

Yes. Cloning textboxes and tables. Which has nothing at all to do with
*removing* all children.


SAM

unread,
Mar 14, 2009, 7:12:51 PM3/14/09
to
Le 3/14/09 12:00 PM, Jorge a écrit :

> On Mar 14, 1:55 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
> wrote:
>>> Their relative speeds : http://jorgechamorro.com/cljs/048/
>> innerHTML 63
>> replaceChild 70
>> removeChild 51
>>
>> Maybe the test would have been better if the 333 inside divs were not
>> empty ?
>
> They're not being cloned in replaceChild (.cloneNode(false)), and it
> takes as long to loop over 333 empty divs as it takes to loop over 333
> non-empty divs... Anyway, now there are 666 non-empty <div>(s) and 666
> children <p>(s) each containing a text. The results are:

Because in your tests you count also the display of the 666 divs,
and as I think that falses the results, I made my page :
<http://cjoint.com/data/drac02WPC8_test_delete_elements.htm>
and I get :

Intel Mac OS X 10.4 Firefox/3.0.7 :
100% removeChild = 169
93% innerHTML = 158
2% replaceChild = 3

iCab.4 :
100% removeChild = 3
67% innerHTML = 2
33% replaceChild = 1

Intel Mac OS X Opera/9.63 :
100% removeChild = 7
29% innerHTML = 2
14% replaceChild = 1

Intel Mac OS X 10_4_11 Safari Version/3.1.2 :
100% removeChild = 3
67% innerHTML = 2
67% replaceChild = 2

MSIE 6.0 - Windows XP SP2
83% removeChild = 50
17% innerHTML = 10
100% replaceChild = 60


Except with IE, innerHTML isn't the faster,
and the winer is replaceChild
as if it would be more difficult to write nothing
than to copy-empty-paste-over a div

--
sm

SAM

unread,
Mar 14, 2009, 7:13:24 PM3/14/09
to
Le 3/14/09 10:34 PM, rf a écrit :

As I told : "essentialy" ...

Anyway, except with IE it seems to me that : innerHTML='';
is not the faster way to remove all those children

<http://cjoint.com/data/drac02WPC8_test_delete_elements.htm>

--
sm

slebetman

unread,
Mar 15, 2009, 12:55:17 AM3/15/09
to

It depends on what the phrase "removing all children of an element"
mean. If the parent "element" in question happens to be a <table> tag
or a <tr> tag then the innerHTML solution may not work on IE.

Jorge

unread,
Mar 15, 2009, 5:33:37 AM3/15/09
to
On Mar 15, 12:13 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
wrote:

>
> Anyway, except with IE it seems to me that :  innerHTML='';
> is not the faster way to remove all those children
>

.innerHTML is always 6.2 times faster... :

"e= container.cloneNode(false); container.parentNode.replaceChild(e,
container); container= e;".length / ",innerHTML= '';".length

:-)

--
Jorge.

Jorge

unread,
Mar 15, 2009, 5:48:09 AM3/15/09
to
On Mar 15, 12:12 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
wrote:

>
> Because in your tests you count also the display of the 666 divs,
> and as I think that falses the results (...)

Yesterday I (sort-of) fixed that already, because now you see the
results in hz and in ms, and there's a fourth row that times
"fillTeContainer" so that it can be (properly) substracted from the
other results.

The problem I'm having with your tests is that it shows 100% in
removeChild and 0% in the others (on mine and on any other ~fast
machine). That's because, as with RobG's tests, you're attempting to
measure a thing that takes about as much or less than the (1..25 ms)
actual resolution of the timer that you're using to measure it... (!),
and that requires a different strategy.

--
Jorge.

Matthias Watermann

unread,
Mar 15, 2009, 6:44:01 AM3/15/09
to
On Sun, 15 Mar 2009 00:13:24 +0100, SAM wrote:

> [...]


> Anyway, except with IE it seems to me that : innerHTML=''; is not the
> faster way to remove all those children
>
> <http://cjoint.com/data/drac02WPC8_test_delete_elements.htm>

Did you try to remove the _last_ child instead of the first? From a
theoretical point of view I would expect it to be faster because the list
of child nodes would only loose its last entry. In contrast removing the
first list entry would require readjusting all the other ones.

But, granted, it would depend on how a certain JavaScript interpreter
actually implemented those linked lists. So it's more out of curiosity
that I'm asking.


--
Matthias
/"\
\ / ASCII RIBBON CAMPAIGN - AGAINST HTML MAIL
X - AGAINST M$ ATTACHMENTS
/ \

Jorge

unread,
Mar 15, 2009, 7:50:10 AM3/15/09
to
On Mar 15, 11:44 am, Matthias Watermann <li...@mwat.de> wrote:
>
> Did you try to remove the _last_ child instead of the first? From a
> theoretical point of view I would expect it to be faster because the list
> of child nodes would only loose its last entry.

Yep, it seems to run slightly faster. (tests updated).

--
Jorge.

rf

unread,
Mar 15, 2009, 7:57:42 AM3/15/09
to
Matthias Watermann wrote:
> On Sun, 15 Mar 2009 00:13:24 +0100, SAM wrote:
>
>> [...]
>> Anyway, except with IE it seems to me that : innerHTML=''; is not
>> the faster way to remove all those children
>>
>> <http://cjoint.com/data/drac02WPC8_test_delete_elements.htm>
>
> Did you try to remove the _last_ child instead of the first? From a
> theoretical point of view I would expect it to be faster because the
> list of child nodes would only loose its last entry. In contrast
> removing the first list entry would require readjusting all the other
> ones.

What do you mean by "readjusting"?

The children would be kept, at the very least, in a doubly linked list or
some such variant. Removing an item from such a list is not dependent where
that item is in the list.


Jorge

unread,
Mar 15, 2009, 8:53:30 AM3/15/09
to
On Mar 15, 12:57 pm, "rf" <r...@z.invalid> wrote:
>
> The children would be kept, at the very least, in a doubly linked list or
> some such variant. Removing an item from such a list is not dependent where
> that item is in the list.

ISTM that the last item is cheaper to remove than any other in the
list because in that case there's just one pointer that needs to be
updated.

--
Jorge.

SAM

unread,
Mar 15, 2009, 10:43:20 AM3/15/09
to
Le 3/15/09 12:50 PM, Jorge a écrit :

With my way to do the tests (time in milli seconds)
as, for instance, in my Safari, the operations run during 1 to 3 ms
... to know which one is faster is of not a big interest.

However, to remove the lastChild seems to be a little bit more difficult
(7 ms instead of 6 ms or 25 <-> 19 ms) then you say the contrary.

Curiously I remade test whith my Firefox freshly opened and I get this
time :

Intel Mac OS X 10.4 - Firefox/3.0.7

100% removeChild = 18 (firstChild) = 23 (lastChild)
61% innerHTML = 11
17% replaceChild = 3

instead of on last time :


100% removeChild = 169
93% innerHTML = 158
2% replaceChild = 3

Something to see with cache ? with CPU ?

Always with my Fx.3 and about removeChild

25ms : while (e = container.lastChild) container.removeChild(e);
19ms : while (e = container.firstChild) container.removeChild(e);
25ms : while (container.hasChildNodes())
container.removeChild(container.lastChild);
17ms : while (container.hasChildNodes())
container.removeChild(container.firstChild);

If the elements to remove are hard coded, the times are larger :
<http://pagesperso-orange.fr/stephane.moriaux/truc/test_delete_html_elements.htm>
(1.5 Mo) (remove = hasChild --> firstChild )

Intel Mac OS X Opera/9.63

100% removeChild = 17
41% innerHTML = 7
24% replaceChild = 4

Intel Mac OS X 10_4_11 Safari/3.1.2
100% removeChild = 58
9% innerHTML = 5
9% replaceChild = 5

Intel Mac OS X 10_4_11 Safari/3.1.2 + cache (after reload)
100% removeChild = 8
63% innerHTML = 5
50% replaceChild = 4

Intel Mac OS X 10.4 Firefox/3.0.7 (cache or no cache but FireBug)
100% removeChild = 48
73% innerHTML = 35
21% replaceChild = 10

--
sm

SAM

unread,
Mar 15, 2009, 10:53:18 AM3/15/09
to
Le 3/15/09 10:33 AM, Jorge a écrit :

I see 2 against 4 (assertions ?)
or 2 more (or less) than the other one :-p

--
sm

SAM

unread,
Mar 15, 2009, 11:16:45 AM3/15/09
to
Le 3/15/09 10:48 AM, Jorge a écrit :

> On Mar 15, 12:12 am, SAM <stephanemoriaux.NoAd...@wanadoo.fr.invalid>
> wrote:
>> Because in your tests you count also the display of the 666 divs,
>> and as I think that falses the results (...)
>
> Yesterday I (sort-of) fixed that already, because now you see the
> results in hz and in ms, and there's a fourth row that times
> "fillTeContainer" so that it can be (properly) substracted from the
> other results.

Don't know how you can count in hz ... ?
(nor what that could mean)

> The problem I'm having with your tests is that it shows 100% in
> removeChild and 0% in the others (on mine and on any other ~fast
> machine). That's because, as with RobG's tests, you're attempting to
> measure a thing that takes about as much or less than the (1..25 ms)

and ?
1 is 1 and 25 is 25, no ?

> actual resolution of the timer that you're using to measure it... (!),
> and that requires a different strategy.

Don't see ...


With your last tests :
<http://homepage.mac.com/jorgechamorro/cljs/048/>

Firefox 3.0.7 on Intel Mac OS X 10.4
innerHTML 220 (4.55ms)
replaceChild 168 (5.95ms)
newContainer 164 (6.1ms)
removeFirstChild 60 (16.67ms)
removeLastChild 56 (17.86ms)

60=16.76 && 56=17.86 ???? inversion of duration ?

The image bellow ... I don't know what it represents (unit of numbers)
- inner (55)
- replace (42)
- remove-first (15)
- remove-last (14)
- new (41)


With Safari, everything except removing is very close

Safari 3.1.2 on Intel Mac OS X 10_4_11
innerHTML 1128 (0.89ms)
replaceChild 1072 (0.93ms)
removeFirstChild 444 (2.25ms)
removeLastChild 440 (2.27ms)
newContainer 1084 (0.92ms)

--
sm

JR

unread,
Mar 15, 2009, 12:24:09 PM3/15/09
to
Hello,
Please take a look at:

http://www.quirksmode.org/dom/innerhtml.html

Cheers,
Joao Rodrigues (JR)

SAM

unread,
Mar 15, 2009, 1:37:54 PM3/15/09
to
Le 3/15/09 5:24 PM, JR a écrit :

> Hello,
> Please take a look at:
>
> http://www.quirksmode.org/dom/innerhtml.html

iCab.4 :
inner = 18 ms or 20 ms
Use W3C DOM table methods = 44 ms
the rest close of 27 ms

My Fx.3 :
inner = 41 and 42 ms
the rest = 109 to 122 ms

Globally, anyone is immediat.

Everybody knows that innerHTML is the best way to insert a table.
Just we have to also know what are the limitations of this way to do.
(row, cell ...)

If I had some attributes to each cell
as 'style', 'onclick', 'onmouseover',
My IE6 runs
- inner_1 in 6980 ms
- inner_2 in 210 ms
and Fx runs both in 130 ms

Certainly in these tests the construction of the "string" has something
to do with the resulting speed in IE.
Is that 'string' usually made by JS or serverside ?

--
sm

SAM

unread,
Mar 15, 2009, 1:48:57 PM3/15/09
to
Le 3/15/09 6:37 PM, SAM a écrit :

>
> If I had some attributes to each cell

If I add some attributes !


--
sm

rf

unread,
Mar 15, 2009, 6:24:39 PM3/15/09
to

Oh my.

There is only one pointer in the first element as well.

And updating that pointer is one machine instruction, of which your computer
can do three thousand million in a second.


Jorge

unread,
Mar 15, 2009, 7:52:24 PM3/15/09
to
On Mar 15, 11:24 pm, "rf" <r...@z.invalid> wrote:
>
> There is only one pointer in the first element as well.

I forgot that e.parentNode has a .lastChild too (I was only thinking
about e.parentNode.firstChild as the start of the linked list). In any
case, when removing an element there are a number of pointers to
adjust (*):

If e is the firstChild: e.nextSibling.previousSibling and
e.parentNode.firstChild.
If e is the lastChild: e.previousSibling.nextSibling and
e.parentNode.lastChild.
If e is the firstChild and the lastChild: e.parentNode.firstChild and
e.parentNode.lastChild
If e is an intermediate: e.previousSibling.nextSibling and
e.nextSibling.previousSibling
In the element that's being removed: e.parentNode= e.nextSibling=
e.previousSibling= null;.

> And updating that pointer is one machine instruction, of which your computer
> can do three thousand million in a second.

Yes, agreed, but *why* does it run faster, then ?
(because it's true that runs faster).

(*)
function removeChild (e) {
if (e.parentNode !== this) {
return; //or throw ?
}

if (e.previousSibling) {
//It's not the firstChild
if (e.previousSibling.nextSibling= e.nextSibling) {
//it's not the lastChild
e.nextSibling.previousSibling= e.previousSibling;
} else {
//it's the lastChild
this.lastChild= e.previousSibling;
}

} else if (e.nextSibling) {
//It's not the lastChild
if (e.nextSibling.previousSibling= e.previousSibling) {
//it's not the firstChild
e.previousSibling.nextSibling= e.nextSibling;
} else {
//it's the firstChild
this.firstChild= e.nextSibling;
}

} else {
//intermediate.
this.firstChild= this.lastChild= null;
}

e.parentNode= e.previousSibling= e.nextSibling= null;
return e;
};

--
Jorge.

RobG

unread,
Mar 15, 2009, 8:22:36 PM3/15/09
to
On Mar 16, 8:24 am, "rf" <r...@z.invalid> wrote:
> Jorge wrote:
> > On Mar 15, 12:57 pm, "rf" <r...@z.invalid> wrote:
>
> >> The children would be kept, at the very least, in a doubly linked
> >> list or some such variant. Removing an item from such a list is not
> >> dependent where that item is in the list.
>
> > ISTM that the last item is cheaper to remove than any other in the
> > list because in that case there's just one pointer that needs to be
> > updated.
>
> Oh my.
>
> There is only one pointer in the first element as well.

No. If you remove the first, the index for each remaining child
element needs to change. If you remove the last, no other element's
index needs to change.


> And updating that pointer is one machine instruction, of which your computer
> can do three thousand million in a second.

Your CPU may process that number of simple instructions per second,
however higher level operations such as removing a node from a
NodeList or updating an index may require tens or hundreds of such
instructions.


--
Rob

RobG

unread,
Mar 15, 2009, 8:36:14 PM3/15/09
to
On Mar 16, 9:52 am, Jorge <jo...@jorgechamorro.com> wrote:
> On Mar 15, 11:24 pm, "rf" <r...@z.invalid> wrote:
>
>
>
> > There is only one pointer in the first element as well.
>
> I forgot that e.parentNode has a .lastChild too (I was only thinking
> about e.parentNode.firstChild as the start of the linked list). In any
> case, when removing an element there are a number of pointers to
> adjust (*):

You can only know that from the source for a particular browser. I
would not expect browsers to maintain all such references, it is
likely more efficient to just keep the indexes updated and calculate
the other properies as required.

In any case, forming a theory as to which method *might* be the
fastest based on some logical deduction just gives you a theory to
test, nothing more. It's the observed behaviour that must be the
guide.


--
Rob

Matthias Watermann

unread,
Mar 16, 2009, 4:22:02 AM3/16/09
to
On Sun, 15 Mar 2009 22:24:39 +0000, rf wrote:

> Jorge wrote:
>> On Mar 15, 12:57 pm, "rf" <r...@z.invalid> wrote:
>>>
>>> The children would be kept, at the very least, in a doubly linked list
>>> or some such variant. Removing an item from such a list is not
>>> dependent where that item is in the list.
>>
>> ISTM that the last item is cheaper to remove than any other in the list
>> because in that case there's just one pointer that needs to be updated.
>
> Oh my.
>
> There is only one pointer in the first element as well.

You're assuming a certain implementation for what in JavaScript appears
as an array: A double linked list with optimisations for the case in
question. And while that might be true (personally I'd be surprised if
it would be otherwise) it's not the only possible implementation. Just
have a look at C++/STL with all its various types of lists.

> And updating that pointer is one machine instruction, of which your
> computer can do three thousand million in a second.

That's not the complete picture. The pointer about to be replaced must
be copied before in order to release the memory it's pointing to. Just
"updating" it (as you call it) would result in serious memory leaks.
Don't forget that we're not taking about JavaScript here (with its more
or less intelligent garbage collector) but about the level below, i.e.
the way a certain JavaScript interpreter itself might be implemented.

rf

unread,
Mar 16, 2009, 5:15:37 AM3/16/09
to
Matthias Watermann wrote:
> On Sun, 15 Mar 2009 22:24:39 +0000, rf wrote:

> You're assuming a certain implementation for what in JavaScript
> appears as an array:

I think I have been suitably proven to be somewhat incomplete in my thinking
here :-)


0 new messages