Skip to content

Commit 409d9ef

Browse files
committed
Merge branch 'vanviegen-master'
2 parents 0e410db + 9c95d0f commit 409d9ef

File tree

9 files changed

+792
-12
lines changed

9 files changed

+792
-12
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This is a simple benchmark for several javascript frameworks. The benchmarks cre
66

77
## Security advice
88

9-
Currently there are 186 implemenations in this repository. It's of course impossible for me to make a security assessment
9+
Currently there are 186 implementations in this repository. It's of course impossible for me to make a security assessment
1010
for all those implementations. `npm ci` and `npm install` can execute arbitraty commands, so they should be executed only for packages you trust. Consequently I build on a dedicated virtual private linux server such that I don't have to install the packages for all those implemenations on my laptop. There's a prebuild build.zip for each chrome release you can download such that you can avoid installing the packages from all implementations.
1111
(I don't know of any (attempted) case for malicious packages in this repository, so please take it just as a general warning.)
1212

@@ -79,7 +79,7 @@ v20.9.0
7979
```
8080

8181
## 1.2 Downloading the pre-built binaries and starting the server
82-
building all frameworks can be challenging. There's a new way that allows to skip that and just run the benchmark without builiding all implementations.
82+
building all frameworks can be challenging. There's a new way that allows to skip that and just run the benchmark without building all implementations.
8383

8484

8585
Start with checking out a tagged release like that. Pick the release that you want (e.g. chrome 100):
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
export function _random(max) {
2+
return Math.round(Math.random() * 1000) % max;
3+
}
4+
5+
const adjectives = [
6+
'pretty',
7+
'large',
8+
'big',
9+
'small',
10+
'tall',
11+
'short',
12+
'long',
13+
'handsome',
14+
'plain',
15+
'quaint',
16+
'clean',
17+
'elegant',
18+
'easy',
19+
'angry',
20+
'crazy',
21+
'helpful',
22+
'mushy',
23+
'odd',
24+
'unsightly',
25+
'adorable',
26+
'important',
27+
'inexpensive',
28+
'cheap',
29+
'expensive',
30+
'fancy'
31+
];
32+
const colors = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];
33+
34+
const nouns = [
35+
'table',
36+
'chair',
37+
'house',
38+
'bbq',
39+
'desk',
40+
'car',
41+
'pony',
42+
'cookie',
43+
'sandwich',
44+
'burger',
45+
'pizza',
46+
'mouse',
47+
'keyboard'
48+
];
49+
50+
let id = 1;
51+
52+
export function buildData(count = 1000) {
53+
54+
const data = [];
55+
56+
for (let i = 0; i < count; i++) {
57+
const adjective = adjectives[_random(adjectives.length)];
58+
const color = colors[_random(colors.length)];
59+
const noun = nouns[_random(nouns.length)];
60+
const label = `${adjective} ${color} ${noun}`;
61+
62+
data.push({ id, label });
63+
64+
id++;
65+
}
66+
67+
return data;
68+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import {$, copy, ref, proxy, onEach} from "aberdeen.js";
2+
import { buildData } from "./build-dummy-data.js";
3+
4+
const data = proxy([]); // [{id, label}, ...]
5+
const selected = proxy({}); // {[selectedId]: true} or {}
6+
7+
// Aberdeen mounts on document.body by default.
8+
$('div', {id: "main"}, 'div.container', () => {
9+
10+
// The buttons
11+
$('div.jumbotron', 'div.row', () => {
12+
$('div.col-md-6', 'h1:Aberdeen-"keyed"');
13+
$('div.col-md-6', 'div.row', () => {
14+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Create 1,000 rows', {
15+
type: "button",
16+
id: "run",
17+
click: () => data.splice(0, data.length, ...buildData())
18+
});
19+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Create 10,000 rows', {
20+
type: "button",
21+
id: "runlots",
22+
click: () => data.splice(0, data.length, ...buildData(10000))
23+
});
24+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Append 1,000 rows', {
25+
type: "button",
26+
id: "add",
27+
click: () => data.push(...buildData())
28+
});
29+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Update every 10th row', {
30+
type: "button",
31+
id: "update",
32+
click: () => {
33+
for(let i=0; i<data.length; i+=10) {
34+
data[i].label += ' !!!';
35+
}
36+
}
37+
});
38+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Clear', {
39+
type: "button",
40+
id: "clear",
41+
click: () => data.length = 0
42+
});
43+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Swap Rows', {
44+
type: "button",
45+
id: "swaprows",
46+
click: () => {
47+
if (data.length > 998) [data[1], data[998]] = [data[998], data[1]];
48+
}
49+
});
50+
});
51+
});
52+
53+
// The table
54+
$('table.table.table-hover.table-striped.test-data', 'tbody', () => {
55+
onEach(data, (item, index) => {
56+
$('tr', () => {
57+
$({".danger": selected[item.id]})
58+
$('td.col-md-1:'+item.id);
59+
$('td.col-md-4', 'a', {text: ref(item,'label')}, {
60+
click: function() {
61+
copy(selected, {[item.id]: true})
62+
}
63+
});
64+
$('td.col-md-1', 'a', 'span.glyphicon.glyphicon-remove', {
65+
"aria-hidden": "true",
66+
click: () => {
67+
// This is very slow, as all later items need to be recreated.
68+
data.splice(index, 1);
69+
}
70+
});
71+
$('td.col-md-6');
72+
});
73+
})
74+
});
75+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Aberdeen-"keyed"</title>
7+
<link href="/css/currentStyle.css" rel="stylesheet" />
8+
<script type="module" src="dist/main.js"></script>
9+
</head>
10+
<body>
11+
</body>
12+
</html>

frameworks/non-keyed/aberdeen/main.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* This implementation uses a sprinkle of non-idiomatic optimization, as the
3+
* delete-row operation doesn't combine well with the row-position based
4+
* operations (swap and update) in Aberdeen.
5+
*
6+
* Aberdeen excels at showing changing list of things in some specified
7+
* sort order (which would be just as fast as sorting by array index, as
8+
* demonstrated by the sort-by-label bonus feature), and doing modifications
9+
* by id. (Which seems a lot more common than what js-framework-benchmark
10+
* wants?)
11+
*
12+
* The idiomatic implementation (with very slow deletes) is in `idiomatic.js`.
13+
*/
14+
15+
import {$, copy, ref, proxy, onEach} from "aberdeen";
16+
import { buildData } from "./build-dummy-data.js";
17+
18+
const unproxiedData = []; // [{id, label}, ...]
19+
const data = proxy(unproxiedData); // [{id, label}, ...]
20+
const selected = proxy({}); // {[selectedId]: true} or {}
21+
const sortByLabel = proxy(false);
22+
23+
// Aberdeen mounts on document.body by default.
24+
$('div', {id: "main"}, 'div.container', () => {
25+
26+
// The buttons
27+
$('div.jumbotron', 'div.row', () => {
28+
$('div.col-md-6', () => {
29+
$('h1:Aberdeen-"keyed"');
30+
$('div.checkbox', 'label', () => {
31+
$('input', {type: 'checkbox'}, {bind: sortByLabel})
32+
$(":Sort by label");
33+
});
34+
})
35+
$('div.col-md-6', 'div.row', () => {
36+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Create 1,000 rows', {
37+
type: "button",
38+
id: "run",
39+
click: () => copy(data, buildData())
40+
});
41+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Create 10,000 rows', {
42+
type: "button",
43+
id: "runlots",
44+
click: () => copy(data, buildData(10000))
45+
});
46+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Append 1,000 rows', {
47+
type: "button",
48+
id: "add",
49+
click: () => data.push(...buildData())
50+
});
51+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Update every 10th row', {
52+
type: "button",
53+
id: "update",
54+
click: () => {
55+
// We need to iterate, because our array can be sparse due to deletes.
56+
// For performance, we're scanning through the unproxied version of our data.
57+
let cnt = 0;
58+
for(let i=0; i<unproxiedData.length; i++) {
59+
if (unproxiedData[i]) {
60+
if (!(cnt++ % 10)) data[i].label += ' !!!';
61+
}
62+
}
63+
}
64+
});
65+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Clear', {
66+
type: "button",
67+
id: "clear",
68+
click: () => data.length = 0
69+
});
70+
$('div.col-sm-6.smallpad', 'button.btn.btn-primary.btn-block:Swap Rows', {
71+
type: "button",
72+
id: "swaprows",
73+
click: () => {
74+
// We need to iterate, because our array can be sparse due to deletes.
75+
// For performance, we're scanning through the unproxied version of our data.
76+
let cnt = 0, first, second;
77+
for(let i=0; i<unproxiedData.length; i++) {
78+
if (unproxiedData[i]) {
79+
if (cnt === 1) first = i;
80+
else if (cnt === 998) {
81+
second = i;
82+
[data[first], data[second]] = [data[second], data[first]];
83+
break;
84+
}
85+
cnt++;
86+
}
87+
}
88+
}
89+
});
90+
});
91+
});
92+
93+
// The table
94+
$('table.table.table-hover.table-striped.test-data', 'tbody', () => {
95+
onEach(data, (item, index) => {
96+
$('tr', () => {
97+
$(() => {
98+
if (selected[item.id]) $('.danger');
99+
})
100+
$('td.col-md-1:'+item.id);
101+
$('td.col-md-4', 'a', {text: ref(item,'label')}, {
102+
click: function() {
103+
copy(selected, {[item.id]: true})
104+
}
105+
});
106+
$('td.col-md-1', 'a', 'span.glyphicon.glyphicon-remove', {
107+
"aria-hidden": "true",
108+
click: () => delete data[index]
109+
});
110+
$('td.col-md-6');
111+
});
112+
}, sortByLabel.value ? item=>item.label : undefined);
113+
});
114+
});

0 commit comments

Comments
 (0)