-
-
Save fredck/f89ecaad2ba99d40c6b274efbf6369f0 to your computer and use it in GitHub Desktop.
Test for different strategies for dumping an in-memory model representation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Case 1: | |
// - format: native DOM (documnet fragment with a clone of body contents) | |
// - output: outerHTML call | |
{ | |
const doc = new DocumentFragment(); | |
doc.append( document.createElement( 'root' ) ); | |
Array.from( document.body.children ).forEach( node => doc.firstElementChild.append( node.cloneNode( true ) ) ); | |
// innerHTML gives the very similar time, so let's go with outerHTML to have a more complete structure. | |
console.time( 'outerHTML time' ); | |
const len = doc.firstElementChild.outerHTML.length; | |
console.timeEnd( 'outerHTML time' ); | |
console.log( 'outerHTML length: ' + len ); | |
} | |
// Case 2: | |
// - format: native JS object | |
// - output: JSON.stringify( object ) | |
{ | |
const root = { type: 'root' }; | |
appendChildren( document.body, root ); | |
function appendChildren( source, target ) { | |
if ( !source.children.length ) { | |
return; | |
} | |
target.children = Array.from( source.childNodes ).map( node => { | |
const child = { type: node.nodeType }; | |
if ( node.nodeType === Node.ELEMENT_NODE ) { | |
child.name = node.nodeName; | |
if ( node.attributes.length ) { | |
child.attribs = Array.from( node.attributes ).reduce( ( attribs, att ) => { | |
attribs[ att.name ] = att.value; | |
return attribs; | |
}, {} ); | |
} | |
appendChildren( node, child ); | |
} else { | |
child.text = node.textContent | |
} | |
return child; | |
} ); | |
} | |
// innerHTML gives the very similar time, so let's go with outerHTML to have a more complete structure. | |
console.time( 'JSON time' ); | |
const len = JSON.stringify( root ).length; | |
console.timeEnd( 'JSON time' ); | |
console.log( 'JSON length: ' + len ); | |
} | |
// Case 3: | |
// - format: "almost string" array tree | |
// - output: array.flat( Infinity ).join( '' ) | |
{ | |
const rootChildren = Array.from( document.body.childNodes ).map( child => getDefinition( child ) ); | |
const root = [ '<root>', ...rootChildren, '</root>' ]; | |
console.time( 'XML Array time' ); | |
const len = root.flat( Infinity ).join( '' ).length; | |
console.timeEnd( 'XML Array time' ); | |
console.log( 'XML Array length: ' + len ); | |
function getDefinitionStart( node ) { | |
let type; | |
const attribs = []; | |
if ( node.nodeType !== Node.ELEMENT_NODE ) { | |
type = 'text'; | |
} else { | |
type = `element`; | |
attribs.push( ' name="', escapeAttrib( node.nodeName ), '"' ); | |
if ( node.attributes.length ) { | |
const attribsObj = Array.from( node.attributes ).reduce( ( attribs, att ) => { | |
attribs[ att.name ] = att.value; | |
return attribs; | |
}, {} ); | |
attribs.push( ' attribs="', escapeAttrib( JSON.stringify( attribsObj ) ), '"' ); | |
} | |
} | |
return `<${ type }${ attribs.join( '' ) }>`; | |
} | |
function getDefinition( node ) { | |
let type, children; | |
if ( node.nodeType !== Node.ELEMENT_NODE ) { | |
type = 'text'; | |
children = [ escapeText( node.textContent ) ]; | |
} else { | |
type = `element`; | |
children = node.childNodes.length ? | |
Array.from( node.childNodes ).map( child => getDefinition( child ) ) : | |
[]; | |
} | |
const definition = [ | |
getDefinitionStart( node ), | |
...children, | |
`</${ type }>` | |
]; | |
definition.type = type; | |
return definition; | |
} | |
function escapeText( value ) { | |
return value | |
.replace( /&/g, '&' ) | |
.replace( /</g, '<' ); | |
} | |
function escapeAttrib( value ) { | |
return value | |
.replace( /&/g, '&' ) | |
.replace( /</g, '<' ) | |
.replace( /"/g, '"' ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just paste this in the console and execute. It'll output timer results for the different strategies.