-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Improve the performance of dimension capturing #86
Comments
@alexreardon The method I found you get several ideas and just want to know when this performance issue will be supported? thank you so much! |
Yeah, right now we collect everything before we allow any movements (simple approach to start with). We are hoping to make this more async. Right now our focus is on auto scrolling and touch support. Although, I am keen to tackle this once those and some other core features are built. For now we are totally open to suggestions on how to make this phase faster. I suspect we wont be able to make it faster, so we will need to make it more async. |
It is currently contained in the Fire Kingdom milestone: https://github.com/atlassian/react-beautiful-dnd/milestone/3 |
@alexreardon thank you so much for your information and hope those performance bottle necks can be solved soon! |
Some thoughts about this one: When can we capture dimensions?On mount ? On mouse down (before drag start) On drag start Moving to async dimension capturingRight now we request all of the dimensions on drag start (in the Solutions in order of complexity1. Publish all dimensions instantly, but do not block user draggingThis is almost the same as it is now, except we allow the user to move the item around before the dimensions are captured. Issues: Simple answer: no longer publish the original location on drag start. I could be persuaded that this is not critical information Keyboard movement 2. Building on solution 1: collect dimensions in batchesThe core idea of this is that we collect the dimensions closest to the lifted Draggable first and work outwards from there - collecting some small number of dimensions at a time (eg 10). If we know the index of each item when the drag starts, then we could implement a batched collection. We could also figure out heuristics for other lists: eg collect dimensions in all droppables within +-5 of the selected index and work outwards in batches of +-5. This would generally yield good results for sibling lists unless the items are drastically different in size. If we assume that we can generate just the centre position of each item really quickly, then the batches could be based on distance from the draggable rather than index. I would need to investigate, but I strongly suspect that 3. Visible dimensions gatheringRather than collecting the dimensions for all |
Hi Alex. First of all, thank you for such a great utility. I've run into this problem (100+ draggables in 40+ droppables) and the drag-lag has become a bit of a show stopper (500ms+ delay when starting a drag operation). I have checked out your code and approach and have a very cursory understanding of how it all works (I will look into it more). It seems that, no matter what you do, there will always be a risk of scaling/performance problems if you collect the dimensions while the user is trying to drag something - especially for users on lower spec machines, and for apps where the number of draggables/droppables can vary significantly (as well as screen sizes). Instant feedback on starting a drag operation is critical from a UX perspective. I have a few thoughts/questions/ideas to start with: Why can't the dimensions be calculated in the componentDidUpdate phase of draggables/droppables? I assume these would only be called when something actually updated within the draggable/droppable hierarchy, and so should be reasonably spread out over time. Any rendering operation could be flagged so that the dimensions are not recalculated while dragging is active? I noticed that you store the current window scroll position when calculating the dimension. This would need to be separated out if you were calculating dimensions during the componentDidUpdate phase (and factored back in dynamically when doing drag/bounds calculations - when getting the clientRect perhaps?). Could there be a way to allow the developer (i.e. me) a way to flag the parent draggable/droppable when something changes (i.e. manual/controlled recalculation of dimensions)? Some sort of redux or HoC thing? A little bit brute force, but could be a potential option if all else fails. Forgive me if I've got the wrong end of things. Just trying to help seed ideas or options. It would be good to understand the problems around the above approach, which may help me look at it again with new eyes. |
Hi Alex, thanks for a great tool. Good work. I wonder if you have any other thoughts about this issue. My team would like to use this utility in our new application, and we have the same performance problems with drag and drop components. Do you have any idea how to fix that? |
I hope to work on this after Candy castle milestone lands |
I have been thinking about this one while away and I have ideas to try out! |
Building on my previous comment I thought of a way to get the index's before the dimensions. Right now we have a
This would allow the drag to start almost instantly while allowing future batching of dimension collecting using a number of different possible techniques |
Do you have any progress on this issue? still waiting to use react-beautiful-dnd after this issue is settled. @alexreardon |
I had a great idea on how to do this. I will share the details next week |
Okay, so here is my current plan: (details still super fuzzy) The dimension marshalRight now we need to request all the dimensions of everything before we start. The key idea is to make this more async. This will also facilitate virtualisation techniques. I propose introducing a new powerful actor: the dimension marshal. This actor would be a lot smarter than what we have today and would allow more creative capturing techniques Phase 1: registration on mountWhen a Phase 2: initial liftIn order to lift we only need to capture a subset of the total dimensions:
At this point we should have enough information to start a drag Phase 3: phased collectionIn this phase the marshal will request dimensions in batches in increasing distance from the source draggable. Both within the current list as well as other lists. We get a number of advantages in this:
This phase is still to be figured out completely. There may be some sort of visibility check added - although these are often expensive so we might as well just collect the dimension. Phase 4:
|
More thoughts: required index propI have been wrestling with how to dynamically get the index of a Advantages:
I do not think this is too much of a burden given that consumers will probably be generating a list of |
I wasn't sure if you were looking for feedback, but here's mine anyway... :) My only concern is capturing all Droppables' dimensions on the initial lift. I can have (easily) 50+ Droppables - almost as many as Draggables - so this would most likely cause a noticeable "hitch" when starting to drag. I agree - most use cases would be using an internal index of their own to sort their Draggables, so I don't think requiring it as a prop would be much of a burden - especially if it helps with your performance strategy. Looking forward to it! |
Good call out regarding the droppable's. We would probably make them phased also. It is a bit tougher because we might also need an index on those which might not make much sense depending on your droppable configuration |
I think this is the same problem that react-virtualized solves, so I might try do a bit of study on that library before I contribute to this discussion. |
Cheers. I think the containers are established up front. Regarding phased droppables - we can probably do some basic phasing without accurate indexes |
I think we are getting close to a solution that will scale well regardless of the amount of droppables that you have 💃 To assist with this |
I'm not sure if I'm having the same issue, but it sounds like it. If I have a large amount of cards, I receive a larger delay. I have about 150 cards, and it takes about a full second from "mouse-downing" to card, to actually picking up the card. The fewer cards I have on the board, the less this delay is. Less than 50, there is little to no delay. Which is confusing because I'm doing absolutely nothing on dragStart. I've put console logs in the render of my columns, and they are definitely not re-rendering on drag start. |
@dcporter44 that is caused by this issue. It is being actively worked on 👍 |
@alexreardon awesome that prototype looks great. |
Still a super work in progress (reordering doesn't work, placeholders are busted - it is unstable 💥) but you can have a play with the prototype containing 500 cards |
Keep in mind that this is 500 |
Speed-wise looks great. Sorry to ask every developer's least favorite question, but how long do you estimate until this is stable? Just trying to time-map out my own project, and trying to decide whether to go figure out React DnD in the meantime |
@dcporter44 it is currently being actively worked on. I try not to give out dates. I think within the next month as a ballpark is a rough guide |
Work in progress stats:Here are some current stats based on the work we are doing. All of the values here are based on a list with 500 Draggables without any virtualisation
Time to liftmaster: 2400ms 200x faster 🤘 Time for movement
master: 12ms 2.4x faster 👍 Time for drop
Have a play |
Impressive. Do you think multiple droppables will make any (negative) difference to the performance? |
Nope |
Updates
|
great idea with displacementList ! |
I am now looking at removing It is tricky to get working, but my initial results are really promising |
The results for this piece of work are looking so good that it will drastically reduce the need for #68 as a go to. |
Nice work @alexreardon — the prototype is looking great! We're also experiencing major initial drag lag with boards that have 100's of cards. Just wondering how progress is going on this? |
Ah, I didn't see that PR... Awesome. Thanks @alexreardon. |
Just saw that checklist is all checked in #226. Getting excited. Is there gonna be an npm publish this week? |
Yep
…On Wed, 10 Jan 2018 at 12:38 pm, Jethro Larson ***@***.***> wrote:
Just saw that checklist is all checked in #226
<#226>. Getting
excited. Is there gonna be an npm publish this week?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#86 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACFN7TFDe-7bubG4k5YSlgr03pMyHFhzks5tJBR5gaJpZM4PSn8n>
.
|
|
Well done @alexreardon, thanks for seeing this through! We'll be upgrading Dovetail to use the latest version soon. |
Amazing! Thanks @alexreardon, excited to try this. |
Currently there is a
DIMENSION_COLLECTING
phase before a drag where we request the dimensions for all of theDroppable
andDraggable
components. This is quite expensive as it calls.getBoundingClientRect
andwindow.getComputedStyle
on all the nodes. We need to think more about how we could improve the performance of this. Some options off the top of my head:The text was updated successfully, but these errors were encountered: