Skip to content

Commit eaf2fce

Browse files
committed
domdiff: raw diffing performane comparison
1 parent d937235 commit eaf2fce

File tree

10 files changed

+464
-0
lines changed

10 files changed

+464
-0
lines changed

frameworks/keyed/domdiff/index.html

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<title>domdiff keyed</title>
6+
<link href="/css/currentStyle.css" rel="stylesheet"/>
7+
<script src='dist/index.js' type="module"></script>
8+
</head>
9+
<body>
10+
<div class="container" id="main">
11+
<div class="jumbotron">
12+
<div class="row">
13+
<div class="col-md-6">
14+
<h1>domdiff keyed</h1>
15+
</div>
16+
<div class="col-md-6">
17+
<div class="row">
18+
<div class="col-sm-6 smallpad">
19+
<button type="button" class="btn btn-primary btn-block" id="run">Create 1,000 rows</button>
20+
</div>
21+
<div class="col-sm-6 smallpad">
22+
<button type="button" class="btn btn-primary btn-block" id="runlots">Create 10,000 rows</button>
23+
</div>
24+
<div class="col-sm-6 smallpad">
25+
<button type="button" class="btn btn-primary
26+
btn-block" id="add">Append 1,000 rows</button>
27+
</div>
28+
<div class="col-sm-6 smallpad">
29+
<button type="button" class="btn btn-primary
30+
btn-block" id="update">Update every 10th row</button>
31+
</div>
32+
<div class="col-sm-6 smallpad">
33+
<button type="button" class="btn btn-primary
34+
btn-block" id="clear">Clear</button>
35+
</div>
36+
<div class="col-sm-6 smallpad">
37+
<button type="button" class="btn btn-primary
38+
btn-block" id="swaprows">Swap Rows</button>
39+
</div>
40+
</div>
41+
</div>
42+
</div>
43+
</div>
44+
<table class="table table-hover table-striped test-data">
45+
<tbody></tbody>
46+
</table>
47+
<span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span>
48+
</div>
49+
</body>
50+
</html>

frameworks/keyed/domdiff/package.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "js-framework-benchmark-domdiff",
3+
"version": "1.0.0",
4+
"description": "domdiff demo",
5+
"main": "index.js",
6+
"js-framework-benchmark": {
7+
"frameworkVersionFromPackage": "domdiff"
8+
},
9+
"scripts": {
10+
"build-dev": "rollup -c -w",
11+
"build-prod": "rollup -c"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "git+https://github.com/krausest/js-framework-benchmark.git"
16+
},
17+
"keywords": [
18+
"domdiff"
19+
],
20+
"author": "Mathis Zeiher",
21+
"license": "Apache-2.0",
22+
"bugs": {
23+
"url": "https://github.com/krausest/js-framework-benchmark/issues"
24+
},
25+
"homepage": "https://github.com/krausest/js-framework-benchmark#readme",
26+
"dependencies": {
27+
"domdiff": "2.2.0"
28+
},
29+
"devDependencies": {
30+
"rollup": "^1.27.0",
31+
"rollup-plugin-node-resolve": "^5.2.0",
32+
"rollup-plugin-terser": "^5.1.2"
33+
}
34+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import resolve from 'rollup-plugin-node-resolve';
2+
import {terser} from 'rollup-plugin-terser';
3+
4+
export default {
5+
input: 'src/index.js',
6+
plugins: [
7+
resolve(),
8+
terser()
9+
],
10+
context: 'null',
11+
moduleContext: 'null',
12+
output: {
13+
file: 'dist/index.js',
14+
format: 'iife',
15+
name: 'app'
16+
}
17+
};

frameworks/keyed/domdiff/src/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import domdiff from 'domdiff';
2+
import {Scope, getRow} from './utils.js';
3+
4+
const tbody = document.querySelector('tbody');
5+
let rows = [].slice.call(tbody.children);
6+
const scope = new Scope(({data, selected}) => {
7+
rows = domdiff(
8+
tbody,
9+
rows,
10+
data.map(item => {
11+
const info = getRow(scope, item);
12+
const {row, select, td} = info;
13+
const {id, label} = item;
14+
if (info.id !== id)
15+
td.textContent = (row.id = (info.id = id));
16+
if (info.label !== label)
17+
select.textContent = (info.label = label);
18+
const danger = id === selected;
19+
if (info.danger !== danger)
20+
row.classList.toggle('danger', (info.danger = danger));
21+
return row;
22+
})
23+
);
24+
});
25+
26+
Object.keys(scope).forEach(id => {
27+
const button = document.querySelector(`#${id.toLowerCase()}`);
28+
if (button)
29+
button.addEventListener('click', () => scope[id]());
30+
});

frameworks/keyed/domdiff/src/utils.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
let did = 1;
2+
const buildData = (count) => {
3+
const adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"];
4+
const colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
5+
const nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"];
6+
const data = [];
7+
for (let i = 0; i < count; i++) {
8+
data.push({
9+
id: did++,
10+
label: adjectives[_random(adjectives.length)] + " " + colours[_random(colours.length)] + " " + nouns[_random(nouns.length)]
11+
});
12+
}
13+
return data;
14+
};
15+
16+
const _random = max => Math.round(Math.random() * 1000) % max;
17+
18+
export function Scope(update) {
19+
const scope = {
20+
add() {
21+
scope.data = scope.data.concat(buildData(1000));
22+
update(scope);
23+
},
24+
run() {
25+
scope.data = buildData(1000);
26+
update(scope);
27+
},
28+
runLots() {
29+
scope.data = buildData(10000);
30+
update(scope);
31+
},
32+
clear() {
33+
scope.data = [];
34+
update(scope);
35+
},
36+
update() {
37+
const {data} = scope;
38+
for (let i = 0, {length} = data; i < length; i += 10)
39+
data[i].label += ' !!!';
40+
update(scope);
41+
},
42+
swapRows() {
43+
const {data} = scope;
44+
if (data.length > 998) {
45+
const tmp = data[1];
46+
data[1] = data[998];
47+
data[998] = tmp;
48+
}
49+
update(scope);
50+
},
51+
delete(id) {
52+
const {data} = scope;
53+
const idx = data.findIndex(d => d.id === id);
54+
data.splice(idx, 1);
55+
update(scope);
56+
},
57+
select(id) {
58+
scope.selected = id;
59+
update(scope);
60+
},
61+
selected: -1,
62+
data: [],
63+
};
64+
return scope;
65+
};
66+
67+
const template = document.createElement('template');
68+
template.innerHTML = `
69+
<tr>
70+
<td class="col-md-1"></td>
71+
<td class="col-md-4">
72+
<a></a>
73+
</td>
74+
<td class="col-md-1"><a><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a></td>
75+
<td class="col-md-6"></td>
76+
</tr>
77+
`.trim();
78+
const tr = template.content.firstChild;
79+
80+
const rows = new WeakMap;
81+
const createRow = (scope, item) => {
82+
const {id, label} = item;
83+
84+
const row = tr.cloneNode(true);
85+
const td = row.querySelector('td');
86+
td.textContent = (row.id = id);
87+
88+
const [select, remove] = row.querySelectorAll('a');
89+
select.textContent = label;
90+
select.addEventListener('click', () => scope.select(id));
91+
remove.addEventListener('click', () => scope.delete(id));
92+
93+
const info = {danger: false, id, label, row, select, td};
94+
rows.set(item, info);
95+
return info;
96+
};
97+
98+
export const getRow = (scope, item) =>
99+
rows.get(item) || createRow(scope, item);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<title>domdiff non-keyed</title>
6+
<link href="/css/currentStyle.css" rel="stylesheet"/>
7+
<script src='dist/index.js' type="module"></script>
8+
</head>
9+
<body>
10+
<div class="container" id="main">
11+
<div class="jumbotron">
12+
<div class="row">
13+
<div class="col-md-6">
14+
<h1>domdiff non-keyed</h1>
15+
</div>
16+
<div class="col-md-6">
17+
<div class="row">
18+
<div class="col-sm-6 smallpad">
19+
<button type="button" class="btn btn-primary btn-block" id="run">Create 1,000 rows</button>
20+
</div>
21+
<div class="col-sm-6 smallpad">
22+
<button type="button" class="btn btn-primary btn-block" id="runlots">Create 10,000 rows</button>
23+
</div>
24+
<div class="col-sm-6 smallpad">
25+
<button type="button" class="btn btn-primary
26+
btn-block" id="add">Append 1,000 rows</button>
27+
</div>
28+
<div class="col-sm-6 smallpad">
29+
<button type="button" class="btn btn-primary
30+
btn-block" id="update">Update every 10th row</button>
31+
</div>
32+
<div class="col-sm-6 smallpad">
33+
<button type="button" class="btn btn-primary
34+
btn-block" id="clear">Clear</button>
35+
</div>
36+
<div class="col-sm-6 smallpad">
37+
<button type="button" class="btn btn-primary
38+
btn-block" id="swaprows">Swap Rows</button>
39+
</div>
40+
</div>
41+
</div>
42+
</div>
43+
</div>
44+
<table class="table table-hover table-striped test-data">
45+
<tbody></tbody>
46+
</table>
47+
<span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span>
48+
</div>
49+
</body>
50+
</html>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "js-framework-benchmark-domdiff",
3+
"version": "1.0.0",
4+
"description": "domdiff demo",
5+
"main": "index.js",
6+
"js-framework-benchmark": {
7+
"frameworkVersionFromPackage": "domdiff"
8+
},
9+
"scripts": {
10+
"build-dev": "rollup -c -w",
11+
"build-prod": "rollup -c"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "git+https://github.com/krausest/js-framework-benchmark.git"
16+
},
17+
"keywords": [
18+
"domdiff"
19+
],
20+
"author": "Mathis Zeiher",
21+
"license": "Apache-2.0",
22+
"bugs": {
23+
"url": "https://github.com/krausest/js-framework-benchmark/issues"
24+
},
25+
"homepage": "https://github.com/krausest/js-framework-benchmark#readme",
26+
"dependencies": {
27+
"domdiff": "2.2.0"
28+
},
29+
"devDependencies": {
30+
"rollup": "^1.27.0",
31+
"rollup-plugin-node-resolve": "^5.2.0",
32+
"rollup-plugin-terser": "^5.1.2"
33+
}
34+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import resolve from 'rollup-plugin-node-resolve';
2+
import {terser} from 'rollup-plugin-terser';
3+
4+
export default {
5+
input: 'src/index.js',
6+
plugins: [
7+
resolve(),
8+
terser()
9+
],
10+
context: 'null',
11+
moduleContext: 'null',
12+
output: {
13+
file: 'dist/index.js',
14+
format: 'iife',
15+
name: 'app'
16+
}
17+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import domdiff from 'domdiff';
2+
import {Scope, getRow, spliceRows} from './utils.js';
3+
4+
const tbody = document.querySelector('tbody');
5+
let rows = [].slice.call(tbody.children);
6+
const scope = new Scope(({data, selected}) => {
7+
rows = domdiff(
8+
tbody,
9+
rows,
10+
data.map((item, index) => {
11+
const info = getRow(scope, item, index);
12+
const {row, select, td} = info;
13+
const {id, label} = item;
14+
if (info.id !== id)
15+
td.textContent = (row.id = (info.id = id));
16+
if (info.label !== label)
17+
select.textContent = (info.label = label);
18+
const danger = id === selected;
19+
if (info.danger !== danger)
20+
row.classList.toggle('danger', (info.danger = danger));
21+
return row;
22+
})
23+
);
24+
spliceRows(rows.length);
25+
});
26+
27+
Object.keys(scope).forEach(id => {
28+
const button = document.querySelector(`#${id.toLowerCase()}`);
29+
if (button)
30+
button.addEventListener('click', () => scope[id]());
31+
});

0 commit comments

Comments
 (0)