Skip to content

Commit 7899b82

Browse files
committed
Merge branch 'master' of github.com:krausest/js-framework-benchmark
2 parents e0d712a + 0dd28e4 commit 7899b82

38 files changed

+6566
-7345
lines changed

frameworks/keyed/ivi/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dist
33

44
node_modules
55

6+
.rollup.cache
67
.DS_Store
78
.idea
89
.vscode

frameworks/keyed/ivi/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<body>
1111
<div id="main"></div>
12-
<script type="module" src="dist/main.js"></script>
12+
<script type="module" src="dist/bundle.js"></script>
1313
</body>
1414

1515
</html>

frameworks/keyed/ivi/package-lock.json

Lines changed: 797 additions & 460 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frameworks/keyed/ivi/package.json

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"private": true,
33
"name": "js-framework-benchmark-ivi",
4+
"type": "module",
45
"version": "1.0.0",
56
"description": "Benchmark for ivi",
67
"author": "Stefan Krause",
@@ -13,17 +14,19 @@
1314
"frameworkHomeURL": "https://github.com/localvoid/ivi"
1415
},
1516
"scripts": {
16-
"build-dev": "rollup -c rollup.config.js",
17-
"build-prod": "rollup -c rollup.config.js"
17+
"build-dev": "rollup -c rollup.config.mjs",
18+
"build-prod": "rollup -c rollup.config.mjs"
1819
},
1920
"dependencies": {
20-
"ivi-html": "0.27.0",
21-
"ivi": "0.27.1"
21+
"ivi": "2.0.0"
2222
},
2323
"devDependencies": {
24-
"rollup": "1.15.6",
25-
"rollup-plugin-node-resolve": "5.0.3",
26-
"rollup-plugin-replace": "2.2.0",
27-
"rollup-plugin-terser": "5.0.0"
24+
"tslib": "2.5.0",
25+
"typescript": "4.9.5",
26+
"rollup": "3.19.1",
27+
"@rollup/plugin-node-resolve": "15.0.1",
28+
"@rollup/plugin-terser": "0.4.0",
29+
"@rollup/plugin-typescript": "11.0.0",
30+
"@ivi/rollup-plugin": "2.0.0"
2831
}
29-
}
32+
}

frameworks/keyed/ivi/rollup.config.js

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { nodeResolve } from "@rollup/plugin-node-resolve";
2+
import typescript from "@rollup/plugin-typescript";
3+
import terser from "@rollup/plugin-terser";
4+
import { ivi } from "@ivi/rollup-plugin";
5+
6+
const TERSER_OPTIONS = {
7+
compress: {
8+
inline: 2,
9+
reduce_vars: false,
10+
passes: 5,
11+
booleans: false,
12+
comparisons: false,
13+
keep_infinity: true,
14+
},
15+
toplevel: true,
16+
mangle: true,
17+
module: true,
18+
};
19+
20+
export default {
21+
input: "./src/main.ts",
22+
output: {
23+
file: "./dist/bundle.js",
24+
format: "es",
25+
strict: true,
26+
sourcemap: false,
27+
},
28+
watch: {
29+
clearScreen: false,
30+
},
31+
plugins: [
32+
nodeResolve(),
33+
typescript(),
34+
ivi(),
35+
terser(TERSER_OPTIONS),
36+
],
37+
};

frameworks/keyed/ivi/src/main.js

Lines changed: 0 additions & 96 deletions
This file was deleted.

frameworks/keyed/ivi/src/main.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { component, List } from "ivi";
2+
import { type Dispatch, useReducer } from "ivi/state";
3+
import { htm } from "ivi/template";
4+
import { createRoot, updateRoot } from "./root.js";
5+
import { Entry, State, Action, ActionType } from "./types.js";
6+
7+
const random = (max: number) => Math.round(Math.random() * 1000) % max;
8+
const A = ["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"];
9+
const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
10+
const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"];
11+
12+
let nextId = 1;
13+
function buildData(count: number): Entry[] {
14+
const data = Array(count);
15+
for (let i = 0; i < count; i++) {
16+
data[i] = { id: nextId++, label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}` };
17+
}
18+
return data;
19+
}
20+
21+
const getEntryId = (entry: Entry) => entry.id;
22+
23+
const INITIAL_STATE: State = { data: [], selected: 0 };
24+
25+
function appStateReducer(state: State, action: Action): State {
26+
switch (action.type) {
27+
case ActionType.Run:
28+
return { ...state, data: buildData(1000) };
29+
case ActionType.RunLots:
30+
return { ...state, data: buildData(10000) };
31+
case ActionType.Add:
32+
return { ...state, data: [...state.data, ...buildData(1000)] };
33+
case ActionType.Update: {
34+
const data = state.data.slice();
35+
for (let i = 0; i < data.length; i += 10) {
36+
const r = data[i];
37+
data[i] = { id: r.id, label: r.label + " !!!" };
38+
}
39+
return { ...state, data };
40+
}
41+
case ActionType.SwapRows: {
42+
const data = state.data.slice();
43+
const tmp = data[1];
44+
data[1] = data[998];
45+
data[998] = tmp;
46+
return { ...state, data };
47+
}
48+
case ActionType.Select: {
49+
return { ...state, selected: action.entry.id };
50+
}
51+
case ActionType.Remove: {
52+
const data = state.data.slice();
53+
data.splice(data.indexOf(action.entry), 1);
54+
return { ...state, data };
55+
}
56+
case ActionType.Clear:
57+
return INITIAL_STATE;
58+
}
59+
}
60+
61+
interface RowProps {
62+
readonly dispatch: Dispatch<Action>;
63+
readonly entry: Entry;
64+
readonly selected: boolean;
65+
}
66+
67+
const Row = component<RowProps>(() => {
68+
let _props: RowProps;
69+
const onSelect = () => { _props.dispatch({ type: ActionType.Select, entry: _props.entry }); };
70+
const onRemove = () => { _props.dispatch({ type: ActionType.Remove, entry: _props.entry }); };
71+
return (props) => (
72+
_props = props,
73+
htm`
74+
tr${props.selected ? "danger" : ""}
75+
td.col-md-1 =${props.entry.id}
76+
td.col-md-4
77+
a @click=${onSelect} =${props.entry.label}
78+
td.col-md-1
79+
a @click=${onRemove}
80+
span.glyphicon.glyphicon-remove :aria-hidden='true'
81+
td.col-md-6
82+
`
83+
);
84+
}, (a, b) => a.entry === b.entry && a.selected === b.selected);
85+
86+
const Button = (text: string, id: string, onClick: () => void) => htm`-c
87+
div.col-sm-6.smallpad
88+
button.btn.btn-primary.btn-block :type='button' :id=${id} @click=${onClick}
89+
${text}
90+
`;
91+
92+
const App = component((c) => {
93+
const [state, dispatch] = useReducer(c, INITIAL_STATE, appStateReducer);
94+
95+
const buttons = [
96+
Button("Create 1,000 rows", "run", () => { dispatch({ type: ActionType.Run }); }),
97+
Button("Create 10,000 rows", "runlots", () => { dispatch({ type: ActionType.RunLots }); }),
98+
Button("Append 1,000 rows", "add", () => { dispatch({ type: ActionType.Add }); }),
99+
Button("Update every 10th row", "update", () => { dispatch({ type: ActionType.Update }); }),
100+
Button("Clear", "clear", () => { dispatch({ type: ActionType.Clear }); }),
101+
Button("Swap Rows", "swaprows", () => { dispatch({ type: ActionType.SwapRows }); }),
102+
];
103+
104+
return () => {
105+
const { data, selected } = state();
106+
return htm`-c
107+
div.container
108+
div.jumbotron
109+
div.row
110+
div.col-md-6
111+
h1 'ivi'
112+
div.col-md-6
113+
div.row ${buttons}
114+
table.table.table-hover.table-striped.test-data
115+
${data.length
116+
? htm`tbody ${List(data, getEntryId, (entry) => Row({ dispatch, entry, selected: entry.id === selected }))}`
117+
: htm`tbody`}
118+
span.preloadicon.glyphicon.glyphicon-remove :aria-hidden='true'
119+
`;
120+
};
121+
});
122+
123+
updateRoot(
124+
createRoot(document.getElementById("main")!),
125+
App(),
126+
);

frameworks/keyed/ivi/src/root.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Basic Scheduler implementation for the benchmark to disable microtask batching.
2+
// https://github.com/localvoid/ivi#custom-scheduler
3+
4+
import { dirtyCheck, SNode, SRoot, VAny } from "ivi";
5+
import { Flags, RENDER_CONTEXT, createSNode, mount, update } from "ivi";
6+
7+
export const createRoot = (p: Element): SRoot<null> => (
8+
createSNode(
9+
Flags.Root,
10+
{
11+
d: {
12+
f: Flags.Root,
13+
p1: (root: SRoot) => {
14+
dirtyCheck(root.c as SNode, 0);
15+
root.f = Flags.Root;
16+
},
17+
p2: null,
18+
},
19+
p: { p, n: null },
20+
},
21+
null,
22+
null,
23+
null,
24+
)
25+
);
26+
27+
export const updateRoot = (root: SRoot<null>, v: VAny): void => {
28+
const domSlot = root.v.p;
29+
RENDER_CONTEXT.p = domSlot.p;
30+
RENDER_CONTEXT.n = domSlot.n;
31+
root.c = (
32+
(root.c === null)
33+
? mount(root, v)
34+
: update(root, root.c as SNode, v, 0)
35+
);
36+
};

0 commit comments

Comments
 (0)