Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
innerHTML vs updateDOM
(version: 2)
Comparing performance of:
innerHTML vs updateDOM vs updateDOMChildren
Created:
8 years ago
by:
Registered User
Jump to the latest result
HTML Preparation code:
<div class="original">original</div> <div class="updated">updated</div>
Script Preparation code:
var baseDOM = document.querySelector('.original'); var updateDOM = document.querySelector('.updated') var DOMUpdates = [ 'content updated', 'content <b>updated</b>', 'content <b>updated</b> more', '<p>content <b>updated</b> more</p>', `<div class="one"> <div>content<b>updated</b></div> <span>more</span> </div>`, `<div class="one"> <div>content</div> sass>as <b>updated</b>aaa <span>more</span> </div>`, `<div class="dos"> <div>content</div> sass>as <b>updated</b>aaa <span>more</span> </div>`, `<div class="dos"> <div>content</div> sass>as <b>updated</b>aaa <list>more</list> </div>`, `<div class="dos"> <div>content</div> sass>as <b>updated</b>aaa <list> <p>1</p> </list> </div>`, `<div class="dos"> <div>content</div> sass>as <b>updated</b>aaa <list> <p>1</p> <p>2</p> </list> </div>`, `<div class="dos"> <div>content</div> sass>as <b>updated</b>aaa <list> <p>1</p> <p>2</p> <p>3</p> </list> </div>`, ]; function cleanChildNodes(node) { for (var n = 0; n < node.childNodes.length; n++) { var child = node.childNodes[n]; if ( child.nodeType === 8 || (child.nodeType === 3 && !/\S/.test(child.nodeValue)) ) { node.removeChild(child); n--; } else if (child.nodeType === 1) { cleanChildNodes(child); } } } function _updateDomElement(oldDom, newDom) { cleanChildNodes(oldDom) cleanChildNodes(newDom) var newDomChildren = Array.from(newDom.childNodes); var oldDomChildren = Array.from(oldDom.childNodes); var isTextNode = (node) => node.nodeType === Node.TEXT_NODE; for (let iD = oldDomChildren.length - 1; iD >= newDomChildren.length; iD--) { oldDom.removeChild(oldDomChildren[iD]); } newDomChildren.forEach((element, index) => { var oldElement = oldDomChildren[index]; if (!oldElement) { oldDom.appendChild(element.cloneNode(true)); } else if ( isTextNode(element) && isTextNode(oldElement) && oldElement.nodeValue !== element.nodeValue ) { oldElement.nodeValue = element.nodeValue } else if (isTextNode(oldElement) && !isTextNode(element)) { oldDom.replaceChild(element.cloneNode(true), oldElement); } else if (element.nodeName !== oldElement.nodeName) { oldElement.outerHTML = element.outerHTML || '' } else if (element.outerHTML !== oldElement.outerHTML) { Array.from(element.attributes || []).forEach(attr => { const oldAttr = oldElement.getAttribute(attr.name); if (!oldAttr || oldAttr !== attr.value) { oldElement.setAttribute(attr.name, attr.value); } }) if (oldElement.attributes.length > element.attributes.length) { Array.from(oldElement.attributes || []).forEach(attr => { if (!element.attributes[attr.name]) { oldElement.removeAttribute(attr.name); } }) } if (element.value !== oldElement.value) { console.log("Value ", element.className); oldElement.value = element.value; } if (element.childNodes.length) { _updateDomElement(oldElement, element) } else if (element.innerText != oldElement.innerText) { console.log("innerText ", element.className); oldElement.innerText = element.innerText; } } }) //Security check if (newDom.innerHTML.replace(/\s+/g, '') !== oldDom.innerHTML.replace(/\s+/g, '')) { console.warn(` Force innerHTML substitution :( OLD: ${oldDom.innerHTML.replace(/\s+/g, '')} NEW: ${newDom.innerHTML.replace(/\s+/g, '')} `); oldDom.innerHTML = newDom.innerHTML; } } function _updateDomElementChildren(oldDom, newDom) { const newDomChildren = Array.from(newDom.children); const oldDomChildren = Array.from(oldDom.children); const isTextNode = (node) => node.nodeType === Node.TEXT_NODE; for (let iD = oldDomChildren.length - 1; iD >= newDomChildren.length; iD--) { oldDom.removeChild(oldDomChildren[iD]); } newDomChildren.forEach((element, index) => { const oldElement = oldDomChildren[index]; if (!oldElement) { oldDom.appendChild(element.cloneNode(true)); } else if ( isTextNode(element) && isTextNode(oldElement) && oldElement.nodeValue !== element.nodeValue ) { oldElement.nodeValue = element.nodeValue } else if (isTextNode(oldElement) && !isTextNode(element)) { oldDom.replaceChild(element.cloneNode(true), oldElement); } else if (element.nodeName !== oldElement.nodeName) { oldElement.outerHTML = element.outerHTML || '' console.warn(`different nodeName ${oldElement.nodeName} != ${element.nodeName}`); } else if (element.outerHTML !== oldElement.outerHTML) { Array.from(element.attributes || []).forEach(attr => { const oldAttr = oldElement.getAttribute(attr.name); if (!oldAttr || oldAttr !== attr.value) { oldElement.setAttribute(attr.name, attr.value); } }) if (oldElement.attributes.length > element.attributes.length) { Array.from(oldElement.attributes || []).forEach(attr => { if (!element.attributes[attr.name]) { oldElement.removeAttribute(attr.name); } }) } if (element.value !== oldElement.value) { oldElement.value = element.value; } if (element.children.length) { _updateDomElementChildren(oldElement, element) } else if(element.textContent != oldElement.textContent){ oldElement.textContent = element.textContent } } }) //Security check if (newDom.innerHTML.replace(/\s+/g, '') !== oldDom.innerHTML.replace(/\s+/g, '')) { console.warn(` Force innerHTML substitution :( OLD: ${oldDom.innerHTML.replace(/\s+/g, '')} NEW: ${newDom.innerHTML.replace(/\s+/g, '')} `); oldDom.innerHTML = newDom.innerHTML; } }
Tests:
innerHTML
DOMUpdates.forEach(update => { updateDOM.innerHTML = update baseDOM.innerHTML = updateDOM.innerHTML })
updateDOM
DOMUpdates.forEach(update => { updateDOM.innerHTML = update _updateDomElement(baseDOM, updateDOM) })
updateDOMChildren
DOMUpdates.forEach(update => { updateDOM.innerHTML = update _updateDomElementChildren(baseDOM, updateDOM) })
Rendered benchmark preparation results:
Suite status:
<idle, ready to run>
Run tests (3)
Previous results
Fork
Test case name
Result
innerHTML
updateDOM
updateDOMChildren
Fastest:
N/A
Slowest:
N/A
Latest run results:
No previous run results
This benchmark does not have any results yet. Be the first one
to run it!
Autogenerated LLM Summary
(model
llama3.2:3b
, generated one year ago):
I'll provide an analysis of the code snippet and benchmark results. **Code Analysis** The provided code appears to be a JavaScript function that updates DOM elements using a `forEach` loop. It takes in an array of updates (`DOMUpdates`) and iterates through each update, applying changes to the corresponding DOM element. The function uses various checks to determine whether to replace or update specific properties of the DOM element. The code snippet includes several methods, such as `_updateDomElement`, `_updateDomElementChildren`, and `isTextNode`. These methods seem to be responsible for updating the child elements, children's text content, and checking if an element is a text node. **Benchmark Results** The benchmark results show three test cases: "innerHTML", "updateDOM", and "updateDOMChildren". The results indicate that: 1. The "innerHTML" test case has the highest number of executions per second (1280.17), suggesting that this test is the most efficient. 2. The "updateDOM" test case has a significantly lower number of executions per second (570.09), indicating that updating the DOM element is slower than just setting the innerHTML. 3. The "updateDOMChildren" test case has the lowest number of executions per second (513.56), suggesting that updating child elements is the slowest part. **Possible Optimizations** Based on the benchmark results, potential optimizations could be: 1. **Avoid unnecessary DOM updates**: Check if an update only affects a small subset of properties or attributes before applying it. 2. **Use caching**: Store the result of expensive operations (e.g., `_updateDomElement`) and reuse them instead of recalculating them on every iteration. 3. **Optimize child element updates**: Use techniques like batch processing, chunking, or lazy loading to reduce the number of DOM updates when dealing with a large number of child elements. Keep in mind that without more context about the specific use case and requirements, these suggestions are speculative.
Related benchmarks:
innerHTML vs updateDOM
innerHTML vs updateDOM
querySelectorAll() vs getElementsByTagName() - with constant
querySelector(class) vs classList.some
Comments
Confirm delete:
Do you really want to delete benchmark?