4 ms·
We at ClinchPad, which also uses a card based layout similar to Trello, faced the same issues. For every 100 cards, it'd add another 1-2 seconds to the load tim
by cmadan 13y ago
We at ClinchPad, which also uses a card based layout similar to Trello, faced the same issues. For every 100 cards, it'd add another 1-2 seconds to the load time meaning when you got to about 700 cards it would be close to 10 seconds of load time.
Here's how I fixed it
1. I added pagination - Load only 300 cards, paginate to load more. We found that while some people had 300+ cards in their default view, most never actually utilised the view usually using a filter to bring down the no of cards to a more manageable level.
That still left about 3-6 seconds of page load time for 300 cards. Unacceptable. So these where the further steps I took to fix it.
2. The main culprit after some rudimentary profiling seemed to be the jQuery's .html('') tag. Apparently it does some cleanup which takes awhile on a huge DOM block with lots of attached events. Replaced it with by looping through each child node in the DOM block and removing them with removeChild. Achieved 8x speedup, loading time down to 1-2 seconds with 300 cards.
3. Second culprit was the jQuery UI's droppable and draggable initiations was taking awhile. Hacked around this by putting the jQuery UI's droppable and draggable initiations inside a setTimeout thats fired in 100ms. Of course, this doesn't affect the actual rendering time but the perceived rendering time is now <1sec because the pipeline loads instantly and it is usually 1-2 seconds before the user does an action on the UI.
All in all, just less than <20 lines of code changed but took me two full days to figure it out. At one point, I was looking through jQuery UI's droppable code and futility seeing how I could optimize it. :)
- applecore 13y agoCool product. Looks similar to Pipedrive[1]. Incidentally, they came before Trello. [1]: https://www.pipedrive.com/ https://www.pipedrive.com/
- cmadan 13y agoThanks! :)
- spicyj 13y ago> The main culprit after some rudimentary profiling seemed to be the jQuery's .html('') tag. Apparently it does some cleanup which takes awhile on a huge DOM block with lots of attached events. Replaced it with by looping through each child node in the DOM block and removing them with removeChild. It's important to let jQuery clean up its event handlers, otherwise you'll end up with memory leaks.
- asolove 13y agoThis is important to remember but hopefully not relevant. If you have event handlers on each card instead of delegating them to the container, that's a performance problem all by itself.
- vonseel 13y agoCan you clarify what you mean here? If I were writing a Backbone app, you mean I should bind to data attributes or similar instead of creating a new view for each item in a list?
- asolove 13y agoIf you have a list of thousands of items, attaching event handlers to each of those items separately is relatively expensive, although it makes the view code nicer. If you are as serious about performance as these people, you would want to add delegated events on the parent level. There is a writeup about doing this in Backbone [1] although I can't vouch for it. In fairness, getting really good dom performance out of Backbone is hard because of the lack of built-in delegated event support and the non-synchronized redraws. If you have big apps that need to be super-fast, either read up on dom performance practices and adopt some helper libraries along with Backbone, or try a framework that has its own draw cycle and delegated event support. [1] http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/ http://lostechies.com/derickbailey/2011/10/11/backbone-js-ge...
- crescentfresh 13y ago> getting really good dom performance out of Backbone is hard because of the lack of built-in delegated event support It actually is builtin: https://github.com/jashkenas/backbone/blob/1.1.0/backbone.js#L1072 https://github.com/jashkenas/backbone/blob/1.1.0/backbone.js... In fact it takes a bit of effort to not use event delegation when setting up your events dict.
- 13y ago
- frik 13y agoMy tips: Avoid JQuery and use JavaScript 5 native API, if it's reasonable target (no IE8 < 9). Check out http://jsperf.com/popular http://jsperf.com/popular and use fast (and sane) methods.
- michaelmior 13y agoWhat does "no IE8 < 9" mean? No versions of IE less than 8, less than 9, or something else?
- henryw 13y agoFor #2, attached events in the child nodes may still be bound. This may lead to more memory usage than needed. Of course, if you don't have any bound events in the children, it'll work. Maybe a work around for any child events would be to delegate them on the parent container and just remove that one when you clear everything.
- ohwp 13y agoAbout events: a nice trick is to add event listeners to the window only and check the event.target. This method is used in game dev a lot.
- tracker1 13y ago+1 where it makes sense.. however this doesn't work well with a modular application, and could lead to a lot of higher level handlers/listeners. I think the more expensive cost is cleanup, or lack of proper cleanup leading to memory leaks... I'll usually detach nodes to cleanup, and put them into a queue that's run in a setTimeout loop... that way they don't slow down the UI.