-
Notifications
You must be signed in to change notification settings - Fork 79
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
Performance enhancement feature: Item groups #11
Conversation
These changes make it so that the collection of cells used by section managers gets frozen after cells have been registered, which improves performance when calculating display items.
Sorry for my delay😔. I will review this PR today and try to fix the tests. Thanks a lot! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Could you add some documents for the new group
feature ?
The broken test seems a little bit flaky and it can be reproduced on linux. |
@starkwang Cheers, glad you could test it on your machine to help narrow down where the issue lies. |
And sure, I'll create the documentation later on today or this weekend. |
src/VirtualCollection.vue
Outdated
totalWidth: 0 | ||
totalWidth: 0, | ||
displayItems: [], | ||
groupManagers: [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The groupManagers
doesn't need to be bind. Can you move it to the created()
method ? This can fix the flaky test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to have worked, thanks.
Moves the `groupManagers` property of `VirtualCollection` out of the data object to prevent Vue making it reactive. This may help resolve a flaky unit test when running on Linux.
Before this gets merged, would you me to commit the stuff under |
@TAGC Thanks for contribution! You don't need to commit the stuff under |
Introduces an "item group" feature that can potentially improve performance for certain use cases of this library.
Motivation
In some cases the collection you pass to a
VirtualCollection
might contain logically separate types of items that change at different rates. For example, in my case I useVirtualCollection
to represent a 2D cartesian grid-space, with two types of objects used in the collection:Grid items are arbitrary objects displayed on the grid. These are passed to the grid as props and so depend entirely on the application consuming my library. The collection of grid items may change frequently. On the other hand, grid tiles are controlled entirely by my grid library and only need to be changed ("regenerated") when the grid is resized.
As vue-virtual-collection currently treats all items in the collection equally, it will invoke
cellSizeAndPositionGetter
, register cells, etc. for every single item in the collection whenever a single item changes. Consider a case where a 100x100 grid is created and 10 grid items are placed on it. If a single grid item changes,VirtualCollection
will perform this procedure for all 10,000 tiles and 10 grid items even though only a single grid item has changed.However, with the concept of "item groups" I can pass grid tiles and grid items to
VirtualCollection
as separate groups, and when an item changesVirtualCollection
will only process the group that contains that item. In this scenario, when a grid item changes it cuts the number of elements operated on from 10,010 to just 10, a reduction of ~99.9%. This can help significantly improve performance.Implementation
Clients of this library can opt-in to using groups by passing an array of objects with the form
{ group: [...] }
, where[...]
represents the items of the collection belonging to a specific group. In the scenario given above,:collection="[...tiles, ...items]"
would get replaced with:collection="[ { group: [] }, { group: [] } ]"
, where the first array would be updated to contain the tiles and the second to contain the grid items.Internally,
VirtualCollection
creates separate watchers for each group in the collection, so that any changes that are limited to a specific group of items will only cause the watcher for that group to fire.This feature does not present breaking changes - it is still possible to pass a flat array of items to
:collection
, in which case it gets wrapped as a single group. This means that all existing usages of the library should work as before, without significant changes in performance. I have confirmed this is the case with my library, and all existing unit tests continue to pass.Benchmarks
Below is a comparison of the performance changes introduced for a demo project based on my grid library, which in turn depends on vue-virtual-collection. The profiles shown below were captured in Chrome devtools on a mid-2014 MacBook Pro running macOS High Sierra 10.13.5. For both profiles, I keep the grid stationary (so that tiles don't regenerate), so that only the grid items change.
Over the course of a second, I observe a reduction in scripting time from 191.4ms to 107.5 ms, a ~44% decrease.
Without Item Grouping
With Item Grouping