Run details:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Chrome 105
Windows
Desktop
2 years ago
Test name Executions per second
innerHTML 490067.9 Ops/sec
removechild & appendChild(cloneNode()) 946406.3 Ops/sec
replaceChildren 438378.3 Ops/sec
Custom deleteChildren 912272.1 Ops/sec
Custom replaceChildren via append 711309.0 Ops/sec
Custom replaceChildren via appendChild 957066.4 Ops/sec
HTML Preparation code:
x
 
1
<style id="CSS_Style">
2
  .expand-inline {
3
    display: block;
4
    padding: 0;
5
  }
6
  .expand-inline a {
7
    display: block;
8
    text-align: left;
9
  }
10
  .expand-inline a:hover {
11
    background-color: rgba(0, 105, 255, 0.05);
12
    text-decoration: none;
13
  }
14
  .pulsar-horizontal { display: inline-block; }
15
  .pulsar-horizontal>div {
16
    display: inline-block;
17
    width: 8px;
18
    height: 8px;
19
    padding: 2px;
20
    background-color: rgb(34, 136, 255);
21
    border-radius: 100%;
22
    animation-name: pulsing;
23
    animation-timing-function: ease-in-out;
24
    animation-iteration-count: infinite;
25
    animation-fill-mode: both;  
26
    animation-duration: 1s;
27
  }
28
  .pulsar-horizontal>div::nth-child(1) { animation-delay: 0s; }
29
  .pulsar-horizontal>div::nth-child(2) { animation-delay: 0.25s; }
30
  .pulsar-horizontal>div::nth-child(3) { animation-delay: 0.5s; }
31
  @keyframes pulsing {
32
    0%, 100%  {  transform: scale(0); opacity: 0.5; }
33
    50%       {  transform: scale(1); opacity: 1; }
34
  }
35
</style>
36
<template id='ELEMENTS'>
37
  <div class="pulsar-horizontal"><div></div><div></div><div></div></div> 
38
  <span class="expand-text">
39
    <a href="/r/IdiotsInCars/comments/vz8iju/other_driver_said_i_hit_him_technically_true_but/ig7o5tm/">continue this thread</a>
40
  </span>
41
  <a href="/r/IdiotsInCars/comments/vz8iju/other_driver_said_i_hit_him_technically_true_but/ig7o5tm/">continue this thread</a>
42
  <span class="deepthread expand-inline" data-comment-ids="ig7o5tm">
43
     <a href="/r/IdiotsInCars/comments/vz8iju/other_driver_said_i_hit_him_technically_true_but/ig7o5tm/">continue this thread</a>
44
     ::after
45
     <span class="gray">&nbsp;(3 replies)</span>
46
  </span> 
47
</template>
48
49
<div id="container">
50
</div>
51
52
53
  
Script Preparation code:
 
const template = document.getElementById('ELEMENTS').content;
var RESOURCES = {
  pulsar:       template.children[0].cloneNode(true),
  pulsarStr:    template.children[0].outerHTML,
  expand:       template.children[1].cloneNode(true),
  expandStr:    template.children[1].outerHTML,
  a:            template.children[2].cloneNode(true),
  aStr:         template.children[2].outerHTML, 
  deepthread:   template.children[3].cloneNode(true), 
  container:    document.getElementById('container'),
  get deepthreads() {
    return Array.from(this.container.childNodes);
  },
  deleteChildren(root) {
    while (root.firstChild) { root.lastChild.remove(); }
    return root;
  },  
  replaceChildren_append(root, ...replacements) {
    while (root.firstChild) { root.lastChild.remove(); }
    root.append(...replacements);
    return root;
  },  
  replaceChildren_appendChild(root, ...replacements) {
    while (root.firstChild) { root.lastChild.remove(); }
    for(let len=replacements.length, i=0; i<len; ++i) { root.appendChild(replacements[i]); }
    return root;
  }, 
};
for(let { container, deepthread }=RESOURCES, i = 0; i < 100; i++) {
  container.appendChild(deepthread.cloneNode(true));
}
Tests:
  • innerHTML

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsarStr, expandStr } = RESOURCES; 
    for(let len=deepthreads.length, i=0; i<len; ++i) {  
      deepthreads[i].innerHTML = pulsarStr; 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) {  
      deepthreads[i].innerHTML = expandStr; 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) {  
      deepthreads[i].innerHTML = ''; 
    }
    container.innerHTML = '';
  • removechild & appendChild(cloneNode())

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsar, expand } = RESOURCES;
    for(let child, dt, len=deepthreads.length, i=0; i<len; ++i) { (dt = deepthreads[i]);
      while ((child=dt.lastChild)!==null) { child.remove(); }
      dt.appendChild(pulsar.cloneNode(true));
    }
    for(let child, dt, len=deepthreads.length, i=0; i<len; ++i) { (dt = deepthreads[i]);
      while ((child=dt.lastChild)!==null) { child.remove(); }
      dt.appendChild(expand.cloneNode(true));
    }
    for(let child, dt, len=deepthreads.length, i=0; i<len; ++i) { (dt = deepthreads[i]);
      while ((child=dt.lastChild)!==null) { child.remove(); }
    }
    for(let child; (child=container.lastChild)!==null; ) { 
      child.remove() 
    }
  • replaceChildren

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsar, expand } = RESOURCES;
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deepthreads[i].replaceChildren(pulsar.cloneNode(true));
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deepthreads[i].replaceChildren(expand.cloneNode(true));
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deepthreads[i].replaceChildren();
    }
    container.replaceChildren();
  • Custom deleteChildren

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsar, expand,  deleteChildren } = RESOURCES;
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deleteChildren(deepthreads[i]).appendChild(pulsar.cloneNode(true));                                                               
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deleteChildren(deepthreads[i]).appendChild(expand.cloneNode(true));  
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      deleteChildren(deepthreads[i]);  
    }
    deleteChildren(container); 
  • Custom replaceChildren via append

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsar, expand, replaceChildren_append } = RESOURCES;
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_append(deepthreads[i], pulsar.cloneNode(true)); 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_append(deepthreads[i], expand.cloneNode(true)); 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_append(deepthreads[i]); 
    }
    replaceChildren_append(container); 
  • Custom replaceChildren via appendChild

     
    // caching vars doubles bench speed. The length of the scope chain to access values from preparation is excessive
    const { container, deepthreads, pulsar, expand, replaceChildren_appendChild } = RESOURCES;
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_appendChild(deepthreads[i], pulsar.cloneNode(true)); 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_appendChild(deepthreads[i], expand.cloneNode(true)); 
    }
    for(let len=deepthreads.length, i=0; i<len; ++i) { 
      replaceChildren_appendChild(deepthreads[i]); 
    }
    replaceChildren_appendChild(container);