akita
akita copied to clipboard
EntityDirtyCheckPlugin is extremely slow in larger (>1000 entities) stores
I'm submitting a...
[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[ x ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:
Current behavior
If you try to execute EntityDirtyCheckPlugin.reset() (no params!) method with store having larger (>1000) amount of entries, procedure is very slow, and grows exponentially.
Expected behavior
EntityDirtyCheckPlugin should be tracking dirty state of each entry (can do it on demand) and revert value only for dirty elements. Otherwise, it could execute diff function first, then update values (it looks it updates all values, no matter if they were dirty or not). It would be nice to get something like "selectDirty()" as side effect, what gives array of currently dirty IDs.
Minimal reproduction of the problem with instructions
https://stackblitz.com/edit/akita-store-tuvxrd
Please press edit, then reset buttons. Enter todo.service.ts and play with for loop value
What is the motivation / use case for changing the behavior?
I have bigger table of data on UI side, with few editable columns and commit/cancel buttons. Commit should get diff and commit changes, cancel should revert changes before editing. The table allows edit in multiple rows and value is commited once when user decides to (it could be after editing single record or multiple records).
Environment
Angular version: X.Y.Z
Browser:
- [ x ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
For Tooling issues:
- Node version: XX
- Platform:
Others:
EntityDirtyCheckPlugin maintains a DirtyCheckPlugin for every entity.
EntityDirtyCheckPlugin.reset() calls DirtyCheckPlugin.reset() for each DirtyCheckPlugin.
each DirtyCheckPlugin.reset() calls AkitaPlugin.updateStore()
AkitaPlugin.updateStore() calls EntityStore.update()
EntityStore.update() calls updateEntities(), which iterates over every entity AGAIN in this segment:
entities: { ...stateEntities, ...updatedEntities }
This is O(n^2). We may be able improve this to O(n) if we used upsertMany() inside EntityDirtyCheckPlugin.reset().
You are welcome to submit a PR
will do once I get some free time