Skip to content

Commit

Permalink
docs(readme): update benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
unadlib committed Dec 21, 2024
1 parent 3a94de4 commit 6384324
Show file tree
Hide file tree
Showing 11 changed files with 541 additions and 230 deletions.
37 changes: 11 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,19 @@ sequenceDiagram

## Performance

Measure(ops/sec) to update 50K arrays and 1K objects, bigger is better([view source](./scripts/benchmark.ts)). [Coaction v0.1.5 vs Zustand v5.0.2]

![Benchmark](benchmark.jpg)

Measure(ops/sec) to update 10K arrays, bigger is better([view source](https://github.com/unadlib/mutative/blob/main/test/performance/benchmark.ts)).

| Library | Test Case | Ops/sec |
| -------------- | ------------------------------- | ------- |
| @coaction/mobx | bigInitWithoutRefsWithoutAssign | 37.44 |
| mobx | bigInitWithoutRefsWithoutAssign | 37.67 |
| coaction | bigInitWithoutRefsWithoutAssign | 18,809 |
| mobx-keystone | bigInitWithoutRefsWithoutAssign | 8.53 |
| @coaction/mobx | bigInitWithoutRefsWithAssign | 1.54 |
| mobx | bigInitWithoutRefsWithAssign | 10.78 |
| coaction | bigInitWithoutRefsWithAssign | 45.20 |
| mobx-keystone | bigInitWithoutRefsWithAssign | 0.13 |
| @coaction/mobx | bigInitWithRefsWithoutAssign | 14.99 |
| mobx | bigInitWithRefsWithoutAssign | 16.68 |
| coaction | bigInitWithRefsWithoutAssign | 255 |
| mobx-keystone | bigInitWithRefsWithoutAssign | 2.35 |
| @coaction/mobx | bigInitWithRefsWithAssign | 1.01 |
| mobx | bigInitWithRefsWithAssign | 7.71 |
| coaction | bigInitWithRefsWithAssign | 57.22 |
| mobx-keystone | bigInitWithRefsWithAssign | 0.11 |
| @coaction/mobx | init | 38.57 |
| mobx | init | 43.88 |
| coaction | init | 8,523 |
| mobx-keystone | init | 41.19 |

This table benchmarks various state management libraries on large initialization tasks. Coaction stands out dramatically, performing at least hundreds of times faster in certain scenarios. For example, in the “bigInitWithoutRefsWithoutAssign” test, Coaction achieves 18,809 ops/sec compared to MobX’s 37.67 ops/sec—over 500 times faster. Similarly, in the “init” test, Coaction reaches 8,523 ops/sec versus MobX’s 43.88 ops/sec—an increase of roughly 200 times. Additionally, Coaction consistently outperforms other libraries across various initialization scenarios, showcasing its exceptional efficiency in handling large-scale data initialization. These results highlight Coaction’s superior performance and make it a highly effective solution for managing complex state in modern front-end applications.
```
Coaction x 4,837 ops/sec ±3.79% (65 runs sampled)
Coaction with Mutative x 4,276 ops/sec ±3.04% (85 runs sampled)
Zustand x 4,753 ops/sec ±3.52% (75 runs sampled)
Zustand with Immer x 251 ops/sec ±0.26% (93 runs sampled)
Zustand with Mutative x 4,292 ops/sec ±3.30% (72 runs sampled)
The fastest method is Coaction,Zustand
```

> We will also provide more complete benchmarking.
Expand Down
Binary file modified benchmark.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"version": "changeset version && node ./scripts/bump-peer-dep-ranges.js",
"publish": "lerna exec --no-private --no-bail -- npm publish --access=public",
"update:version": "lerna version --amend --no-git-tag-version",
"benchmark": "tsx ./packages/coaction-mobx/test/benchmark/index.ts"
"benchmark:mobx": "tsx ./packages/coaction-mobx/test/benchmark/index.ts",
"benchmark": "NODE_ENV='production' tsx ./scripts/benchmark.ts"
},
"authors": [
"Michael Lin <[email protected]> (https://github.com/unadlib)"
Expand Down Expand Up @@ -80,6 +81,7 @@
"commitizen": "^4.3.0",
"cz-conventional-changelog": "^3.3.0",
"husky": "^3.1.0",
"immer": "^10.1.1",
"jest": "^29.7.0",
"jest-config": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
Expand All @@ -95,7 +97,8 @@
"tsx": "^4.19.2",
"typescript": "^5.6.3",
"vue": "^3.0.11",
"webpack-dev-middleware": "^3.6.0"
"webpack-dev-middleware": "^3.6.0",
"zustand-mutative": "^1.2.0"
},
"config": {
"commitizen": {
Expand Down
33 changes: 33 additions & 0 deletions packages/coaction-mobx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,39 @@ store.setState(() => {
});
```

## Performance

![Benchmark](./benchmark.jpg)

Measure(ops/sec) to update 10K arrays, bigger is better([view source](https://github.com/unadlib/mutative/blob/main/test/performance/benchmark.ts)).

| Library | Test Case | Ops/sec |
| -------------- | ------------------------------- | ------- |
| @coaction/mobx | bigInitWithoutRefsWithoutAssign | 37.44 |
| mobx | bigInitWithoutRefsWithoutAssign | 37.67 |
| coaction | bigInitWithoutRefsWithoutAssign | 18,809 |
| mobx-keystone | bigInitWithoutRefsWithoutAssign | 8.53 |
| @coaction/mobx | bigInitWithoutRefsWithAssign | 1.54 |
| mobx | bigInitWithoutRefsWithAssign | 10.78 |
| coaction | bigInitWithoutRefsWithAssign | 45.20 |
| mobx-keystone | bigInitWithoutRefsWithAssign | 0.13 |
| @coaction/mobx | bigInitWithRefsWithoutAssign | 14.99 |
| mobx | bigInitWithRefsWithoutAssign | 16.68 |
| coaction | bigInitWithRefsWithoutAssign | 255 |
| mobx-keystone | bigInitWithRefsWithoutAssign | 2.35 |
| @coaction/mobx | bigInitWithRefsWithAssign | 1.01 |
| mobx | bigInitWithRefsWithAssign | 7.71 |
| coaction | bigInitWithRefsWithAssign | 57.22 |
| mobx-keystone | bigInitWithRefsWithAssign | 0.11 |
| @coaction/mobx | init | 38.57 |
| mobx | init | 43.88 |
| coaction | init | 8,523 |
| mobx-keystone | init | 41.19 |

This table benchmarks various state management libraries on large initialization tasks. Coaction stands out dramatically, performing at least hundreds of times faster in certain scenarios. For example, in the “bigInitWithoutRefsWithoutAssign” test, Coaction achieves 18,809 ops/sec compared to MobX’s 37.67 ops/sec—over 500 times faster. Similarly, in the “init” test, Coaction reaches 8,523 ops/sec versus MobX’s 43.88 ops/sec—an increase of roughly 200 times. Additionally, Coaction consistently outperforms other libraries across various initialization scenarios, showcasing its exceptional efficiency in handling large-scale data initialization. These results highlight Coaction’s superior performance and make it a highly effective solution for managing complex state in modern front-end applications.

> We will also provide more complete benchmarking.
## Documentation

You can find the documentation [here](https://github.com/unadlib/coaction).
Binary file added packages/coaction-mobx/benchmark.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion packages/coaction-mobx/test/benchmark/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import https from 'https';
import path from 'path';
import { Suite } from 'benchmark';
import QuickChart from 'quickchart-js';
import { createCoactionMobxStore } from './coaction-mobx';
Expand Down Expand Up @@ -316,7 +317,9 @@ try {
const chart = new QuickChart();
chart.setConfig(config);
console.log('config:', JSON.stringify(config));
const file = fs.createWriteStream('benchmark.jpg');
const file = fs.createWriteStream(
path.resolve(__dirname, '../../benchmark.jpg')
);
https.get(chart.getUrl(), (response) => {
response.pipe(file);
file.on('finish', () => {
Expand Down
74 changes: 45 additions & 29 deletions packages/core/src/handleState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,14 @@ export const handleState = <T extends CreateState>(
: merge;
const enablePatches =
store.transport ?? (options as StoreOptions<T>).enablePatches;
if (!enablePatches) {
if (internal.mutableInstance) {
if (internal.actMutable) {
internal.actMutable(() => {
fn.apply(null);
});
return [];
}
fn.apply(null);
if (!enablePatches && internal.mutableInstance) {
if (internal.actMutable) {
internal.actMutable(() => {
fn.apply(null);
});
return [];
}
// best performance by default for immutable state
// TODO: supporting nested set functions?
try {
internal.backupState = internal.rootState;
internal.rootState = createWithMutative(
internal.rootState,
(draft) => {
internal.rootState = draft as Draft<any>;
return fn.apply(null);
}
);
} catch (error) {
internal.rootState = internal.backupState;
throw error;
}
if (internal.updateImmutable) {
internal.updateImmutable(internal.rootState as T);
} else {
internal.listeners.forEach((listener) => listener());
}
fn.apply(null);
return [];
}
internal.backupState = internal.rootState;
Expand Down Expand Up @@ -122,6 +99,45 @@ export const handleState = <T extends CreateState>(
throw new Error('setState cannot be called within the updater');
}
internal.isBatching = true;
if (
!store.share &&
!(options as StoreOptions<T>).enablePatches &&
!internal.mutableInstance
) {
if (typeof next === 'function') {
try {
internal.backupState = internal.rootState;
internal.rootState = createWithMutative(
internal.rootState,
(draft) => {
internal.rootState = draft as Draft<any>;
return next(internal.module);
}
);
} catch (error) {
internal.rootState = internal.backupState;
internal.isBatching = false;
throw error;
}
} else {
const copy = {} as T;
const rootState = internal.rootState as T;
for (const key of Object.keys(rootState)) {
copy[key] = rootState[key];
}
for (const key of Object.keys(next!)) {
copy[key] = next![key];
}
internal.rootState = copy;
}
if (internal.updateImmutable) {
internal.updateImmutable(internal.rootState as T);
} else {
internal.listeners.forEach((listener) => listener());
}
internal.isBatching = false;
return [];
}
let result: void | [] | [any, Patches, Patches];
try {
const isDrafted = internal.mutableInstance && isDraft(internal.rootState);
Expand Down
Loading

0 comments on commit 6384324

Please sign in to comment.