diff --git a/demos/benchmark/index.html b/demos/benchmark/index.html
new file mode 100644
index 00000000..4bf97680
--- /dev/null
+++ b/demos/benchmark/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+ Dlight.JS
+
+
+
+
+
+
+
diff --git a/demos/benchmark/package.json b/demos/benchmark/package.json
new file mode 100644
index 00000000..63425f3a
--- /dev/null
+++ b/demos/benchmark/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "dev",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@babel/standalone": "^7.22.4",
+ "@inula/next": "workspace:*",
+ "@iandx/easy-css": "^0.10.14",
+ "babel-preset-inula-next": "workspace:*"
+ },
+ "devDependencies": {
+ "typescript": "^5.2.2",
+ "vite": "^4.4.9",
+ "vite-plugin-inula-next": "workspace:*"
+ },
+ "keywords": [
+ "dlight.js"
+ ]
+}
diff --git a/demos/benchmark/src/main.jsx b/demos/benchmark/src/main.jsx
new file mode 100644
index 00000000..599e008c
--- /dev/null
+++ b/demos/benchmark/src/main.jsx
@@ -0,0 +1,102 @@
+import { createSignal, createSelector, batch } from 'solid-js';
+import { render } from 'solid-js/web';
+
+let idCounter = 1;
+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'],
+ colours = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'],
+ nouns = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse', 'keyboard'];
+
+function _random (max) {
+ return Math.round(Math.random() * 1000) % max;
+}
+
+function buildData(count) {
+ let data = new Array(count);
+ for (let i = 0; i < count; i++) {
+ const [label, setLabel] = createSignal(`${adjectives[_random(adjectives.length)]} ${colours[_random(colours.length)]} ${nouns[_random(nouns.length)]}`);
+ data[i] = {
+ id: idCounter++,
+ label, setLabel
+ };
+ }
+ return data;
+}
+
+function Button ({ id, text, fn }) {
+ return (
+
+
+
+ );
+}
+
+function App () {
+ let data = [];
+ let selected = null;
+ function run() {
+ data = buildData(1000);
+ }
+ function runLots() {
+ data = buildData(10000);
+ }
+ function add() {
+ data.push(...buildData(1000));
+ }
+ function update() {
+ for (let i = 0; i < data.length; i += 10) {
+ data[i].label += ' !!!';
+ }
+ }
+ function swapRows() {
+ if (data.length > 998) {
+ [data[1], data[998]] = [data[998], data[1]];
+ }
+ }
+ function clear() {
+ data = [];
+ }
+ function remove(id) {
+ data = data.filter(d => d.id !== id);
+ }
+ function select(id) {
+ selected = id;
+ }
+
+ return (
+
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+ {/*for const { id, label } of data*/}
+
+
+ |
+ |
+ |
+ |
+
+
+
+
+
+ );
+}
+
+render('main', App);
diff --git a/demos/benchmark/vite.config.js b/demos/benchmark/vite.config.js
new file mode 100644
index 00000000..0531be34
--- /dev/null
+++ b/demos/benchmark/vite.config.js
@@ -0,0 +1,13 @@
+import { defineConfig } from 'vite';
+import inula from 'vite-plugin-inula-next';
+
+export default defineConfig({
+ server: {
+ port: 4320,
+ },
+ base: '',
+ optimizeDeps: {
+ disabled: true,
+ },
+ plugins: [inula({ files: '**/*.{tsx,jsx}' })],
+});