Skip to content

Instantly share code, notes, and snippets.

@acdha
Last active March 18, 2025 09:12
Show Gist options
  • Select an option

  • Save acdha/092c6d79f9ebb888496c to your computer and use it in GitHub Desktop.

Select an option

Save acdha/092c6d79f9ebb888496c to your computer and use it in GitHub Desktop.
Comparing performance adding rows to a large table using innerHTML, the DOM API, React JSX and, eventually, React.createElement
Render using innerHTML took:0.140s; tbody height=536364px
Render using DOM took:0.076s; tbody height=536364px
Render using React took:1.443s; tbody height=536364px
<!DOCTYPE html>
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>
Dropper – JavaScript Experiment
</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/main.css">
</head>
<body>
<div id="bagger" class="container">
<button id="add-files-innerhtml" class="btn btn-primary">Add rows using innerHTML</button>
<button id="add-files-dom" class="btn btn-primary">Add rows using DOM</button>
<button id="add-files-jsx" class="btn btn-primary">Add rows using React + JSX</button>
<table class="table table-striped"><caption>Current Contents</caption><thead><tr><th class="file-name">Filename</th><th class="file-size">Size</th><th class="file-hash sha1">SHA-1</th><th class="file-hash sha256">SHA-256</th></tr></thead><tbody></tbody></table>
</div>
<script>
var benchmarkRows = 10000;
function displayElapsed(label, endTime, startTime) {
var tbody = document.querySelector('tbody');
// Force layout by hitting tbody.clientHeight:
alert('Render using ' + label + ' took:' + ((endTime - startTime) / 1000).toFixed(3) + 's; tbody height=' + tbody.clientHeight + 'px');
// Reset for back-to-back benchmarks:
tbody.innerHTML = '';
}
document.getElementById('add-files-innerhtml').addEventListener('click', function () {
var startTime = Date.now();
var rowHTML = '<tr><td class="file-name">2015-02-17 21.37.05.jpg</td><td class="file-size">1.58 MB</td><td class="file-hash sha1" title="735388c2a781711009426e4f2952e069afcd6f50">735388c2a781711009426e4f2952e069afcd6f50</td><td class="file-hash sha256" title="fbe056c48fa92a618c0133648676a844187848f7f940a377338ab01410682f2c">fbe056c48fa92a618c0133648676a844187848f7f940a377338ab01410682f2c</td></tr>';
var tbody = document.querySelector('tbody');
var rows = [];
for (var i = 0; i < benchmarkRows; i++) {
rows.push(rowHTML);
}
tbody.innerHTML = rows.join('\n');
displayElapsed('innerHTML', Date.now(), startTime);
});
document.getElementById('add-files-dom').addEventListener('click', function () {
var startTime = Date.now();
var tbody = document.querySelector('tbody');
for (var i = 0; i < benchmarkRows; i++) {
var tr = document.createElement('tr');
var fileName = document.createElement('td');
fileName.className = 'file-name'
fileName.textContent = '2015-02-17 21.37.05.jpg'
tr.appendChild(fileName);
var fileSize = document.createElement('td');
fileSize.className = 'file-size';
fileSize.textContent = '1.58 MB'
tr.appendChild(fileSize);
var sha1 = document.createElement('td');
sha1.className = 'file-hash sha1'
sha1.attributes.title='735388c2a781711009426e4f2952e069afcd6f50'
sha1.textContent = '735388c2a781711009426e4f2952e069afcd6f50'
tr.appendChild(sha1);
var sha256 = document.createElement('td');
sha256.className = 'file-hash sha256'
sha256.attributes.title='fbe056c48fa92a618c0133648676a844187848f7f940a377338ab01410682f2c';
sha256.textContent = 'fbe056c48fa92a618c0133648676a844187848f7f940a377338ab01410682f2c';
tr.appendChild(sha256);
tbody.appendChild(tr);
}
displayElapsed('DOM', Date.now(), startTime);
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
<script type="text/jsx">
var TableComponent = React.createClass({
getInitialState: function () {
return {displayRows: false};
},
showRows: function () {
var startTime = Date.now();
this.setState({displayRows: true});
this.forceUpdate(function () {
displayElapsed('React JSX', Date.now(), startTime);
});
},
render: function () {
var rows;
if (!this.state.displayRows) {
rows = <tr><td colspan="4"><button className='btn btn-primary' onClick={this.showRows}>Display Rows</button></td></tr>;
} else {
rows = this.props.data.map(function (row, idx) {
return (
<tr key={idx}>
<td className="file-name">{row[0]}</td>
<td class="file-size">{row[1]}</td>
<td class="file-hash sha1" title="{row[2]}">{row[2]}</td>
<td class="file-hash sha256" title="{row[3]}">{row[3]}</td>
</tr>
);
});
}
return (
<table className="table table-striped">
<caption>Current Contents</caption>
<thead>
<tr><th className="file-name">Filename</th><th className="file-size">Size</th><th className="file-hash sha1">SHA-1</th><th className="file-hash sha256">SHA-256</th></tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
)
}
});
document.getElementById('add-files-jsx').addEventListener('click', function () {
var row = ['2015-02-17 21.37.05.jpg', '1.58 MB', '735388c2a781711009426e4f2952e069afcd6f50',
'fbe056c48fa92a618c0133648676a844187848f7f940a377338ab01410682f2c'],
rows = [];
for (var i = 0; i < benchmarkRows; i++) {
rows.push(row);
}
React.render(React.createElement(TableComponent, {data: rows}),
document.querySelector('table'));
});
</script>
</body></html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment