perf(nim): CoW container and model diff utils proposal #19242
+7,159
−251
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
POC (haven't manually tested all the models)
We're currently suffering badly from perf issues related to how we build the nim models, how we share data between nim components, how we update the models and how we emit model update signals.
Long story short I could identify 5 model patterns in the app:
Pattern 1, but the nested models could be fixed with the same approach. The trick is not to create new nested model objects, but to efficiently update the existing onesdelegate(in our case the data owner is the service). This type of model lacks a proper way to efficiently update the model because on everydelegate.getwe're getting the current state. To do an efficient update we'll need the previous version of the data.delegate. AKA perf killersPattern 1The current codebase is just too large to refactor all the models we currently have, so a middle-ground needs to be found and applied.
This PR is a proposal for this middle-ground.
Proposal:
Pattern 1 - apply a helper (
model_sync) that does a data diff and composes a list of bulk operations needed by the model for the update.dataChanged,rowInserted,rowRemovedetc.Pattern 2 - apply the
model_syncfor both main model and the nested modelsPattern 3 - Introducing a
CoWcontainer. This container is owned by the service and shared with the app. The app will have a ref to the container. Whenever data is written in the container, the service object will change, leaving all copies with the old data. This way on every update the models will have a chance of constructing the proper events usingmodel_sync.Downsides- we can't support
ref objectfor the base data type (usually a DTO). We need deep copies on every write. Not a major drawback though since the container itself is supposed to be efficient and the other copies needed through the app should be relatively small.Pattern 4 - Same as Pattern 3, with a nested
model_syncPattern 5 - similar to pattern 1 and 2
Files of interest:
src/app/core/cow_seq.nimsrc/app/modules/shared/model_sync.nim