-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creating observable array should be optimized #68
Comments
Hi @kmalakoff
This part seems quite expensive, how / why is this triggered during the creating of the tags array? (just trying to get the complete image). Because making an object observable in itself should basically side effect free, so how is this one triggered? Does simplifying this code make a difference for the performance? I have no problem cutting the childObserving logic out, but in general that is so cheap that I doubt whether that makes a big difference. But as said I'm a bit puzzled how adding a tag triggers all this logic? |
@mweststrate I'm using chokidar to scan and sync with the filesystem and depending on the files it encounters, it adds tags to a folder node (eg. files map to tags and folders map to nodes). Very asynchronous / event-driven..but it should be cheap because most of the time it finds an existing folder node (the My hypothesis based on comparing using and not using an observable array is that this is just a scale issue that needs an optimization (1000s of nodes being created). I could have a bug somewhere and can investigate further, but the stack trace looked like it confirmed my hypothesis (I could interpreting this incorrectly!)...it looks like there is something slow in there, but I think it is probably just the overhead of doing setup (needed) and tracking (not needed), but it could be something else? (not sure if a computed calculation dependency is somehow slipping in and getting triggered) Which part looks expensive to you? |
@kmalakoff Eh... wait I was reading the chart upside down, hence I was totally confused and wondering how findOrCreate is a side effect of replace :). I usually use the top down view ;). The call stack is findOrCreate > replace > splice > updateLength so that makes perfect sense. I'll look into it! I was cleaning up the code base of the core algorithm a bit anyway, so I did already spot some additional optimization opportunities (both in performance and memory consumption). |
@kmalakoff I've played around with short-circuiting the array initialization, see: In my tests it was a bit faster (but not extremely significant, < 10%). Turns out the actual expensive part is defining the properties on the object. Now basically they can also be defined on the prototype, which saves in my tests 90% of the initialization time: Yet the down side of the latter optimization is that the indexes of the array are no longer reported as being enumerable. This the point where the abstraction of observable arrays is a bit leaky until ES6 proxies are general available; mobservable arrays tries their best to be normal arrays but are in fact objects. For most things this doesn't matter; index or length assignments, array methods etc all work correctly. However, Currently Anyway, would you mind checking both commits above to see whether this makes the performance of arrays acceptable? The first option can be safely applied without breaking anything. This branch is based on the latest transform branch that includes your commits. EDIT: accidentally swapped the commits |
Excellent! I was away from a computer yesterday and will run some performance evaluations this first thing in the morning. As for the tradeoffs:
Definitely, rather than always using slice because creates a copy (this is not guaranteed to scale well with large array sizes due to memory management and the corresponding reference copying operations), I would prefer |
I've run some tests... (1) tags are not observable - it still tracks as expensive from other parts of my code (2) tags are observable - no optimizations yet (3) tags are observable, short-circuiting the array initialization (a6ac0c1) - like you say, not much improvement (4) tags are observable, defining the properties on the object (94151c2) - it doesn't track at all! So I've confirmed like you discovered (4) has removed the expensive part and updateLength / spliceWithArray doesn't even track as significant. I'm going to use this version until it is released and start using transformations today! Thank you for looking into and optimizing this! |
Merged this back to feature/transform and released it as 1.1.6 (without the transform feature). Api changes:
|
Excellent! Thank you so much... |
I added one observable array property to an object and the creation cycle is taking up large amount of time.
I create them like (I really like the idea of shallowObservables for arrays to replace asFlat since I'm using it quite a bit as I optimize):
I think that the creation path for observable arrays should be streamlined rather than using the generic splicing logic...nothing can observe yet, no childObserving logic is needed if the values are flat, etc.
The text was updated successfully, but these errors were encountered: