Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit b3ffb63

Browse files
authored
Merge pull request #169 from agile-ts/develop
New Release 🎉
2 parents 13e4bbe + cef61b6 commit b3ffb63

File tree

149 files changed

+4981
-1331
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+4981
-1331
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
'@agile-ts/api': patch
3+
'@agile-ts/core': patch
4+
'@agile-ts/event': patch
5+
'@agile-ts/logger': patch
6+
'@agile-ts/multieditor': patch
7+
'@agile-ts/proxytree': patch
8+
'@agile-ts/react': patch
9+
'@agile-ts/utils': patch
10+
'@agile-ts/vue': patch
11+
---
12+
13+
#### :rocket: New Feature
14+
* `react`
15+
* [#171](https://github.com/agile-ts/agile/pull/171) Add deps array to useAgile() hook ([@bennodev19](https://github.com/bennodev19))
16+
* `core`, `event`, `react`, `vue`
17+
* [#166](https://github.com/agile-ts/agile/pull/166) Shared Agile Instance ([@bennodev19](https://github.com/bennodev19))
18+
19+
#### :nail_care: Polish
20+
* `api`, `core`, `event`, `logger`, `multieditor`, `react`, `utils`
21+
* [#168](https://github.com/agile-ts/agile/pull/168) Performance optimization ([@bennodev19](https://github.com/bennodev19))
22+
* `core`, `event`, `react`, `vue`
23+
* [#166](https://github.com/agile-ts/agile/pull/166) Shared Agile Instance ([@bennodev19](https://github.com/bennodev19))
24+
25+
#### Committers: 1
26+
- BennoDev ([@bennodev19](https://github.com/bennodev19))
27+

README.md

Lines changed: 99 additions & 68 deletions
Large diffs are not rendered by default.

benchmark/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MANUAL_BENCHMARK=false

benchmark/README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# 🚀️ Benchmarks
2+
3+
The `Benchmark Test Suites` are supposed to showcase where AgileTs is roughly located in terms of performance.
4+
I know a counter doesn't really show real world app performance,
5+
but it is better than nothing.
6+
7+
### What do the results from benchmark js mean?
8+
https://stackoverflow.com/questions/28524653/what-do-the-results-from-benchmark-js-mean
9+
10+
## Counter Benchmark
11+
12+
```ts
13+
1. AgileTs.............43028 ops/se ±2.45 (63 runs sampled)
14+
2. PulseJs.............41086 ops/se ±2.60 (63 runs sampled)
15+
3. Nano Stores.........31933 ops/se ±1.27 (63 runs sampled)
16+
4. Zustand.............29329 ops/se ±1.30 (62 runs sampled)
17+
5. Redux...............28845 ops/se ±2.47 (61 runs sampled)
18+
6. Hookstate...........27555 ops/se ±5.00 (59 runs sampled)
19+
7. Mobx................27427 ops/se ±3.69 (62 runs sampled)
20+
8. Redux-Toolkit.......22191 ops/se ±1.06 (65 runs sampled)
21+
9. Jotai...............22157 ops/se ±4.10 (63 runs sampled)
22+
10. Valtio..............21089 ops/se ±0.77 (63 runs sampled)
23+
11. Recoil..............13926 ops/se ±2.12 (62 runs sampled)
24+
25+
Fastest is AgileTs
26+
```
27+
28+
## 1000 Fields
29+
30+
```ts
31+
// 1 Field
32+
1. Agile nested State..27992 ops/se ±1.73 (64 runs sampled)
33+
2. Pulse Collection....25547 ops/se ±1.04 (64 runs sampled)
34+
3. Agile State.........23962 ops/se ±2.16 (64 runs sampled)
35+
4. Nano Stores.........20662 ops/se ±1.76 (65 runs sampled)
36+
5. Hookstate...........19430 ops/se ±1.81 (61 runs sampled)
37+
6. Agile Collection....18491 ops/se ±2.13 (65 runs sampled)
38+
7. Jotai...............16029 ops/se ±3.39 (62 runs sampled)
39+
8. Mobx................15631 ops/se ±3.42 (61 runs sampled)
40+
9. Redux...............12698 ops/se ±2.86 (61 runs sampled)
41+
10. Recoil..............11183 ops/se ±3.73 (61 runs sampled)
42+
11. Valtio..............9728 ops/se ±2.81 (62 runs sampled)
43+
44+
Fastest is Agile nested State
45+
46+
// 10 Fields
47+
1. Agile nested State..27658 ops/se ±1.99 (64 runs sampled)
48+
2. Pulse Collection....24839 ops/se ±1.31 (65 runs sampled)
49+
3. Agile State.........19853 ops/se ±2.15 (64 runs sampled)
50+
4. Nano Stores.........19479 ops/se ±2.12 (60 runs sampled)
51+
5. Hookstate...........18104 ops/se ±3.37 (60 runs sampled)
52+
6. Jotai...............15472 ops/se ±2.45 (62 runs sampled)
53+
7. Agile Collection....13352 ops/se ±3.67 (61 runs sampled)
54+
8. Recoil..............10522 ops/se ±3.79 (58 runs sampled)
55+
9. Mobx................9477 ops/se ±1.94 (62 runs sampled)
56+
10. Redux...............8434 ops/se ±2.67 (47 runs sampled)
57+
11. Valtio..............3532 ops/se ±2.27 (23 runs sampled)
58+
59+
Fastest is Agile nested State
60+
61+
// 100 Fields
62+
1. Agile nested State..24124 ops/se ±1.05 (65 runs sampled)
63+
2. Pulse Collection....21912 ops/se ±1.35 (66 runs sampled)
64+
3. Nano Stores.........15638 ops/se ±1.63 (62 runs sampled)
65+
4. Hookstate...........13986 ops/se ±2.28 (59 runs sampled)
66+
5. Jotai...............12167 ops/se ±2.78 (63 runs sampled)
67+
6. Agile State.........9175 ops/se ±1.56 (51 runs sampled)
68+
7. Recoil..............8717 ops/se ±3.51 (49 runs sampled)
69+
8. Agile Collection....4177 ops/se ±1.64 (61 runs sampled)
70+
9. Redux...............1763 ops/se ±1.06 (63 runs sampled)
71+
10. Mobx................1699 ops/se ±1.82 (62 runs sampled)
72+
11. Valtio..............432 ops/se ±2.18 (60 runs sampled)
73+
74+
Fastest is Agile nested State
75+
76+
// 1000 Fields
77+
1. Agile nested State..10756 ops/se ±1.43 (58 runs sampled)
78+
2. Pulse Collection....9774 ops/se ±2.39 (58 runs sampled)
79+
3. Hookstate...........4737 ops/se ±4.33 (58 runs sampled)
80+
4. Nano Stores.........4638 ops/se ±6.40 (28 runs sampled)
81+
5. Jotai...............3352 ops/se ±4.17 (53 runs sampled)
82+
6. Recoil..............3139 ops/se ±4.69 (54 runs sampled)
83+
7. Agile State.........1389 ops/se ±1.52 (57 runs sampled)
84+
8. Agile Collection....500 ops/se ±1.89 (61 runs sampled)
85+
9. Redux...............154 ops/se ±1.48 (57 runs sampled)
86+
10. Mobx................144 ops/se ±1.06 (55 runs sampled)
87+
11. Valtio..............37 ops/se ±4.26 (40 runs sampled)
88+
89+
Fastest is Agile nested State
90+
```
91+
92+
## Computed
93+
94+
```ts
95+
1. Agile Hard Coded....32079 ops/se ±1.51 (62 runs sampled)
96+
2. Agile Auto Tracking.30974 ops/se ±2.21 (64 runs sampled)
97+
3. Nano Stores.........28821 ops/se ±1.49 (64 runs sampled)
98+
4. Jotai...............18922 ops/se ±2.12 (61 runs sampled)
99+
5. Recoil..............10103 ops/se ±2.47 (64 runs sampled)
100+
101+
Fastest is Agile Hard Coded
102+
```
103+
104+
## 🏃 Running Benchmarks
105+
106+
The Benchmark tests run on top of the [`benchmark.js` library](https://github.com/bestiejs/benchmark.js/)
107+
via [Playwright](https://github.com/microsoft/playwright) in the Chrome Browser.
108+
109+
Before starting, make sure you are in the `/benchmark` directory.
110+
111+
### 1️⃣ Install dependencies
112+
113+
To prepare the dependencies, run:
114+
```ts
115+
yarn install
116+
```
117+
118+
### 2️⃣ Run Benchmark Test Suite
119+
120+
Execute the benchmark located in `./benchmarks/react/counter`.
121+
```ts
122+
yarn run test:counter
123+
```
124+
125+
## ⭐️ Contribute
126+
127+
Get a part of AgileTs and start contributing. We welcome any meaningful contribution. 😀
128+
To find out more about contributing, check out the [CONTRIBUTING.md](https://github.com/agile-ts/agile/blob/master/CONTRIBUTING.md).
129+
130+
<a href="https://codeclimate.com/github/agile-ts/agile/coverage.svg">
131+
<img src="https://codeclimate.com/github/agile-ts/agile/badges/gpa.svg" alt="Maintainability"/>
132+
</a>
133+
134+
## 🎉 Credits
135+
136+
The Benchmark CLI is inspired by [`exome`](https://github.com/Marcisbee/exome).

benchmark/benchmarkManager.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
export interface CycleResultInterface {
2+
name: string;
3+
opsInSec: number;
4+
failRate: number;
5+
ranSampleCount: number;
6+
ui: any;
7+
}
8+
9+
export function getCycleResult(event: any): CycleResultInterface {
10+
return {
11+
name: event.target.name,
12+
opsInSec: Math.round(event.target.hz),
13+
failRate: event.target.stats.rme.toFixed(2),
14+
ranSampleCount: event.target.stats.sample.length,
15+
ui: {
16+
count: event.target.output,
17+
},
18+
};
19+
}
20+
21+
export function startBenchmarkLog(testSuiteName: string): void {
22+
console.log(`{white Starting Benchmark "{magenta.bold ${testSuiteName}}"..}`);
23+
}
24+
25+
export function cycleLog(
26+
cycleResult: CycleResultInterface,
27+
...addition: any[]
28+
): void {
29+
console.log(
30+
`{gray ..Proceeded {green.bold ${cycleResult.name}} - {yellow ${cycleResult.opsInSec} ops/sec}}`,
31+
...addition
32+
);
33+
}
34+
35+
export function endBenchmarkLog(
36+
testSuiteName: string,
37+
results: CycleResultInterface[],
38+
fastest: string[]
39+
): void {
40+
console.log(`{white ..End Benchmark "{magenta.bold ${testSuiteName}}"}\n\n`);
41+
42+
results.sort((a, b) => {
43+
if (a.opsInSec < b.opsInSec) return 1;
44+
return -1;
45+
});
46+
47+
let resultString = '';
48+
for (let i = 0; i < results.length; i++) {
49+
const cycleResult = results[i];
50+
51+
// Build Cycle Result Log
52+
const cycleString = `{bold.bgGreen ${
53+
i + 1
54+
}.} {bold.blue ${cycleResult.name
55+
.padEnd(20, '.')
56+
.replace(/(\.+)$/, '{red $1}')}}{yellow ${
57+
cycleResult.opsInSec
58+
} ops/se} {gray ±${cycleResult.failRate}%} (${
59+
cycleResult.ranSampleCount
60+
} runs sampled)`;
61+
62+
resultString += `${cycleString}${i < results.length - 1 ? '\n' : ''}`;
63+
}
64+
65+
// Build Leaderboard Header
66+
console.log('{bgYellow.white.bold Leaderboard:}\n');
67+
68+
// Print Leaderboard
69+
console.log(resultString);
70+
71+
// Print fastest
72+
console.log(`\n{bold Fastest is {bold.green ${fastest}}}\n`);
73+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from 'react';
2+
import ReactDom from 'react-dom';
3+
import { createCollection, LogCodeManager } from '@agile-ts/core';
4+
import { useAgile, useValue } from '@agile-ts/react';
5+
6+
LogCodeManager.getLogger().isActive = false;
7+
8+
export default function (target: HTMLElement, fieldsCount: number) {
9+
const FIELDS = createCollection({
10+
initialData: Array.from(Array(fieldsCount).keys()).map((i) => ({
11+
id: i,
12+
name: `Field #${i + 1}`,
13+
})),
14+
});
15+
16+
let updatedFieldsCount = 0;
17+
let renderFieldsCount = 0;
18+
19+
function Field({ index }: { index: number | string }) {
20+
const ITEM = FIELDS.getItem(index);
21+
const item = useAgile(ITEM);
22+
23+
renderFieldsCount++;
24+
25+
return (
26+
<div>
27+
Last {`<Field>`} render at: {new Date().toISOString()}
28+
&nbsp;
29+
<input
30+
value={item?.name}
31+
onChange={(e) => {
32+
ITEM?.patch({ name: e.target.value });
33+
34+
updatedFieldsCount++;
35+
36+
(document.getElementById(
37+
'updatedFieldsCount'
38+
) as any).innerText = updatedFieldsCount;
39+
(document.getElementById(
40+
'renderFieldsCount'
41+
) as any).innerText = renderFieldsCount;
42+
}}
43+
/>
44+
</div>
45+
);
46+
}
47+
48+
function App() {
49+
const fieldKeys = useValue(FIELDS);
50+
51+
return (
52+
<div>
53+
<div>
54+
Last {`<App>`} render at: {new Date().toISOString()}
55+
</div>
56+
<br />
57+
{fieldKeys.map((key, i) => (
58+
<Field key={i} index={key} />
59+
))}
60+
<div id={'updatedFieldsCount'} />
61+
<div id={'renderFieldsCount'} />
62+
</div>
63+
);
64+
}
65+
66+
ReactDom.render(<App key={'agilets-collection'} />, target);
67+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import * as React from 'react';
2+
import * as ReactDom from 'react-dom';
3+
import { createState, LogCodeManager, State } from '@agile-ts/core';
4+
import { useAgile } from '@agile-ts/react';
5+
6+
LogCodeManager.getLogger().isActive = false;
7+
8+
export default function (target: HTMLElement, fieldsCount: number) {
9+
const FIELDS = createState(
10+
Array.from(Array(fieldsCount).keys()).map((i) =>
11+
createState(`Field #${i + 1}`)
12+
)
13+
);
14+
15+
let updatedFieldsCount = 0;
16+
let renderFieldsCount = 0;
17+
18+
function Field({ field }: { field: State<string> }) {
19+
const name = useAgile(field);
20+
21+
renderFieldsCount++;
22+
23+
return (
24+
<div>
25+
Last {`<Field>`} render at: {new Date().toISOString()}
26+
&nbsp;
27+
<input
28+
value={name}
29+
onChange={(e) => {
30+
field.set(e.target.value);
31+
32+
updatedFieldsCount++;
33+
34+
(document.getElementById(
35+
'updatedFieldsCount'
36+
) as any).innerText = updatedFieldsCount;
37+
(document.getElementById(
38+
'renderFieldsCount'
39+
) as any).innerText = renderFieldsCount;
40+
}}
41+
/>
42+
</div>
43+
);
44+
}
45+
46+
function App() {
47+
const fields = useAgile(FIELDS);
48+
return (
49+
<div>
50+
<div>
51+
Last {`<App>`} render at: {new Date().toISOString()}
52+
</div>
53+
<br />
54+
{fields.map((field, index) => (
55+
<Field key={index} field={field} />
56+
))}
57+
<div id={'updatedFieldsCount'} />
58+
<div id={'renderFieldsCount'} />
59+
</div>
60+
);
61+
}
62+
63+
ReactDom.render(<App key={'agilets-nested-state'} />, target);
64+
}

0 commit comments

Comments
 (0)