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

Commit

Permalink
Merge pull request #169 from agile-ts/develop
Browse files Browse the repository at this point in the history
New Release 🎉
  • Loading branch information
bennobuilder authored Jul 10, 2021
2 parents 13e4bbe + cef61b6 commit b3ffb63
Show file tree
Hide file tree
Showing 149 changed files with 4,981 additions and 1,331 deletions.
27 changes: 27 additions & 0 deletions .changeset/serious-terms-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
'@agile-ts/api': patch
'@agile-ts/core': patch
'@agile-ts/event': patch
'@agile-ts/logger': patch
'@agile-ts/multieditor': patch
'@agile-ts/proxytree': patch
'@agile-ts/react': patch
'@agile-ts/utils': patch
'@agile-ts/vue': patch
---

#### :rocket: New Feature
* `react`
* [#171](https://github.com/agile-ts/agile/pull/171) Add deps array to useAgile() hook ([@bennodev19](https://github.com/bennodev19))
* `core`, `event`, `react`, `vue`
* [#166](https://github.com/agile-ts/agile/pull/166) Shared Agile Instance ([@bennodev19](https://github.com/bennodev19))

#### :nail_care: Polish
* `api`, `core`, `event`, `logger`, `multieditor`, `react`, `utils`
* [#168](https://github.com/agile-ts/agile/pull/168) Performance optimization ([@bennodev19](https://github.com/bennodev19))
* `core`, `event`, `react`, `vue`
* [#166](https://github.com/agile-ts/agile/pull/166) Shared Agile Instance ([@bennodev19](https://github.com/bennodev19))

#### Committers: 1
- BennoDev ([@bennodev19](https://github.com/bennodev19))

167 changes: 99 additions & 68 deletions README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions benchmark/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MANUAL_BENCHMARK=false
136 changes: 136 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# 🚀️ Benchmarks

The `Benchmark Test Suites` are supposed to showcase where AgileTs is roughly located in terms of performance.
I know a counter doesn't really show real world app performance,
but it is better than nothing.

### What do the results from benchmark js mean?
https://stackoverflow.com/questions/28524653/what-do-the-results-from-benchmark-js-mean

## Counter Benchmark

```ts
1. AgileTs.............43028 ops/se ±2.45 (63 runs sampled)
2. PulseJs.............41086 ops/se ±2.60 (63 runs sampled)
3. Nano Stores.........31933 ops/se ±1.27 (63 runs sampled)
4. Zustand.............29329 ops/se ±1.30 (62 runs sampled)
5. Redux...............28845 ops/se ±2.47 (61 runs sampled)
6. Hookstate...........27555 ops/se ±5.00 (59 runs sampled)
7. Mobx................27427 ops/se ±3.69 (62 runs sampled)
8. Redux-Toolkit.......22191 ops/se ±1.06 (65 runs sampled)
9. Jotai...............22157 ops/se ±4.10 (63 runs sampled)
10. Valtio..............21089 ops/se ±0.77 (63 runs sampled)
11. Recoil..............13926 ops/se ±2.12 (62 runs sampled)

Fastest is AgileTs
```

## 1000 Fields

```ts
// 1 Field
1. Agile nested State..27992 ops/se ±1.73 (64 runs sampled)
2. Pulse Collection....25547 ops/se ±1.04 (64 runs sampled)
3. Agile State.........23962 ops/se ±2.16 (64 runs sampled)
4. Nano Stores.........20662 ops/se ±1.76 (65 runs sampled)
5. Hookstate...........19430 ops/se ±1.81 (61 runs sampled)
6. Agile Collection....18491 ops/se ±2.13 (65 runs sampled)
7. Jotai...............16029 ops/se ±3.39 (62 runs sampled)
8. Mobx................15631 ops/se ±3.42 (61 runs sampled)
9. Redux...............12698 ops/se ±2.86 (61 runs sampled)
10. Recoil..............11183 ops/se ±3.73 (61 runs sampled)
11. Valtio..............9728 ops/se ±2.81 (62 runs sampled)

Fastest is Agile nested State

// 10 Fields
1. Agile nested State..27658 ops/se ±1.99 (64 runs sampled)
2. Pulse Collection....24839 ops/se ±1.31 (65 runs sampled)
3. Agile State.........19853 ops/se ±2.15 (64 runs sampled)
4. Nano Stores.........19479 ops/se ±2.12 (60 runs sampled)
5. Hookstate...........18104 ops/se ±3.37 (60 runs sampled)
6. Jotai...............15472 ops/se ±2.45 (62 runs sampled)
7. Agile Collection....13352 ops/se ±3.67 (61 runs sampled)
8. Recoil..............10522 ops/se ±3.79 (58 runs sampled)
9. Mobx................9477 ops/se ±1.94 (62 runs sampled)
10. Redux...............8434 ops/se ±2.67 (47 runs sampled)
11. Valtio..............3532 ops/se ±2.27 (23 runs sampled)

Fastest is Agile nested State

// 100 Fields
1. Agile nested State..24124 ops/se ±1.05 (65 runs sampled)
2. Pulse Collection....21912 ops/se ±1.35 (66 runs sampled)
3. Nano Stores.........15638 ops/se ±1.63 (62 runs sampled)
4. Hookstate...........13986 ops/se ±2.28 (59 runs sampled)
5. Jotai...............12167 ops/se ±2.78 (63 runs sampled)
6. Agile State.........9175 ops/se ±1.56 (51 runs sampled)
7. Recoil..............8717 ops/se ±3.51 (49 runs sampled)
8. Agile Collection....4177 ops/se ±1.64 (61 runs sampled)
9. Redux...............1763 ops/se ±1.06 (63 runs sampled)
10. Mobx................1699 ops/se ±1.82 (62 runs sampled)
11. Valtio..............432 ops/se ±2.18 (60 runs sampled)

Fastest is Agile nested State

// 1000 Fields
1. Agile nested State..10756 ops/se ±1.43 (58 runs sampled)
2. Pulse Collection....9774 ops/se ±2.39 (58 runs sampled)
3. Hookstate...........4737 ops/se ±4.33 (58 runs sampled)
4. Nano Stores.........4638 ops/se ±6.40 (28 runs sampled)
5. Jotai...............3352 ops/se ±4.17 (53 runs sampled)
6. Recoil..............3139 ops/se ±4.69 (54 runs sampled)
7. Agile State.........1389 ops/se ±1.52 (57 runs sampled)
8. Agile Collection....500 ops/se ±1.89 (61 runs sampled)
9. Redux...............154 ops/se ±1.48 (57 runs sampled)
10. Mobx................144 ops/se ±1.06 (55 runs sampled)
11. Valtio..............37 ops/se ±4.26 (40 runs sampled)

Fastest is Agile nested State
```

## Computed

```ts
1. Agile Hard Coded....32079 ops/se ±1.51 (62 runs sampled)
2. Agile Auto Tracking.30974 ops/se ±2.21 (64 runs sampled)
3. Nano Stores.........28821 ops/se ±1.49 (64 runs sampled)
4. Jotai...............18922 ops/se ±2.12 (61 runs sampled)
5. Recoil..............10103 ops/se ±2.47 (64 runs sampled)

Fastest is Agile Hard Coded
```

## 🏃 Running Benchmarks

The Benchmark tests run on top of the [`benchmark.js` library](https://github.com/bestiejs/benchmark.js/)
via [Playwright](https://github.com/microsoft/playwright) in the Chrome Browser.

Before starting, make sure you are in the `/benchmark` directory.

### 1️⃣ Install dependencies

To prepare the dependencies, run:
```ts
yarn install
```

### 2️⃣ Run Benchmark Test Suite

Execute the benchmark located in `./benchmarks/react/counter`.
```ts
yarn run test:counter
```

## ⭐️ Contribute

Get a part of AgileTs and start contributing. We welcome any meaningful contribution. 😀
To find out more about contributing, check out the [CONTRIBUTING.md](https://github.com/agile-ts/agile/blob/master/CONTRIBUTING.md).

<a href="https://codeclimate.com/github/agile-ts/agile/coverage.svg">
<img src="https://codeclimate.com/github/agile-ts/agile/badges/gpa.svg" alt="Maintainability"/>
</a>

## 🎉 Credits

The Benchmark CLI is inspired by [`exome`](https://github.com/Marcisbee/exome).
73 changes: 73 additions & 0 deletions benchmark/benchmarkManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
export interface CycleResultInterface {
name: string;
opsInSec: number;
failRate: number;
ranSampleCount: number;
ui: any;
}

export function getCycleResult(event: any): CycleResultInterface {
return {
name: event.target.name,
opsInSec: Math.round(event.target.hz),
failRate: event.target.stats.rme.toFixed(2),
ranSampleCount: event.target.stats.sample.length,
ui: {
count: event.target.output,
},
};
}

export function startBenchmarkLog(testSuiteName: string): void {
console.log(`{white Starting Benchmark "{magenta.bold ${testSuiteName}}"..}`);
}

export function cycleLog(
cycleResult: CycleResultInterface,
...addition: any[]
): void {
console.log(
`{gray ..Proceeded {green.bold ${cycleResult.name}} - {yellow ${cycleResult.opsInSec} ops/sec}}`,
...addition
);
}

export function endBenchmarkLog(
testSuiteName: string,
results: CycleResultInterface[],
fastest: string[]
): void {
console.log(`{white ..End Benchmark "{magenta.bold ${testSuiteName}}"}\n\n`);

results.sort((a, b) => {
if (a.opsInSec < b.opsInSec) return 1;
return -1;
});

let resultString = '';
for (let i = 0; i < results.length; i++) {
const cycleResult = results[i];

// Build Cycle Result Log
const cycleString = `{bold.bgGreen ${
i + 1
}.} {bold.blue ${cycleResult.name
.padEnd(20, '.')
.replace(/(\.+)$/, '{red $1}')}}{yellow ${
cycleResult.opsInSec
} ops/se} {gray ±${cycleResult.failRate}%} (${
cycleResult.ranSampleCount
} runs sampled)`;

resultString += `${cycleString}${i < results.length - 1 ? '\n' : ''}`;
}

// Build Leaderboard Header
console.log('{bgYellow.white.bold Leaderboard:}\n');

// Print Leaderboard
console.log(resultString);

// Print fastest
console.log(`\n{bold Fastest is {bold.green ${fastest}}}\n`);
}
67 changes: 67 additions & 0 deletions benchmark/benchmarks/react/1000fields/bench/agilets/collection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import ReactDom from 'react-dom';
import { createCollection, LogCodeManager } from '@agile-ts/core';
import { useAgile, useValue } from '@agile-ts/react';

LogCodeManager.getLogger().isActive = false;

export default function (target: HTMLElement, fieldsCount: number) {
const FIELDS = createCollection({
initialData: Array.from(Array(fieldsCount).keys()).map((i) => ({
id: i,
name: `Field #${i + 1}`,
})),
});

let updatedFieldsCount = 0;
let renderFieldsCount = 0;

function Field({ index }: { index: number | string }) {
const ITEM = FIELDS.getItem(index);
const item = useAgile(ITEM);

renderFieldsCount++;

return (
<div>
Last {`<Field>`} render at: {new Date().toISOString()}
&nbsp;
<input
value={item?.name}
onChange={(e) => {
ITEM?.patch({ name: e.target.value });

updatedFieldsCount++;

(document.getElementById(
'updatedFieldsCount'
) as any).innerText = updatedFieldsCount;
(document.getElementById(
'renderFieldsCount'
) as any).innerText = renderFieldsCount;
}}
/>
</div>
);
}

function App() {
const fieldKeys = useValue(FIELDS);

return (
<div>
<div>
Last {`<App>`} render at: {new Date().toISOString()}
</div>
<br />
{fieldKeys.map((key, i) => (
<Field key={i} index={key} />
))}
<div id={'updatedFieldsCount'} />
<div id={'renderFieldsCount'} />
</div>
);
}

ReactDom.render(<App key={'agilets-collection'} />, target);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { createState, LogCodeManager, State } from '@agile-ts/core';
import { useAgile } from '@agile-ts/react';

LogCodeManager.getLogger().isActive = false;

export default function (target: HTMLElement, fieldsCount: number) {
const FIELDS = createState(
Array.from(Array(fieldsCount).keys()).map((i) =>
createState(`Field #${i + 1}`)
)
);

let updatedFieldsCount = 0;
let renderFieldsCount = 0;

function Field({ field }: { field: State<string> }) {
const name = useAgile(field);

renderFieldsCount++;

return (
<div>
Last {`<Field>`} render at: {new Date().toISOString()}
&nbsp;
<input
value={name}
onChange={(e) => {
field.set(e.target.value);

updatedFieldsCount++;

(document.getElementById(
'updatedFieldsCount'
) as any).innerText = updatedFieldsCount;
(document.getElementById(
'renderFieldsCount'
) as any).innerText = renderFieldsCount;
}}
/>
</div>
);
}

function App() {
const fields = useAgile(FIELDS);
return (
<div>
<div>
Last {`<App>`} render at: {new Date().toISOString()}
</div>
<br />
{fields.map((field, index) => (
<Field key={index} field={field} />
))}
<div id={'updatedFieldsCount'} />
<div id={'renderFieldsCount'} />
</div>
);
}

ReactDom.render(<App key={'agilets-nested-state'} />, target);
}
Loading

0 comments on commit b3ffb63

Please sign in to comment.