Hacker News new | ask | show | jobs
by asuth 4766 days ago
For our recently launched flashcards tool, we built it in Backbone. Demo: http://quizlet.com/23770911/flashcards

Our experience was that backbone was very helpful in laying out code and providing clean event triggering, but that a lot of it was simply too slow to use. We started out with a View per card, but that was impossibly slow with 100+ cards (and we need to support ~1000+). We ended up with just one view for the Card section, and a view each for the sidebar and options sections. That made it much faster, but also took away many of the benefits of backbone.

We also ran into significant speed problems with model gets and sets. Initializing the data for 200 cards (~10 attributes per card) took hundreds of milliseconds on Chrome and other browsers. We ended up using plain javascript objects for the hottest parts of that code.

Overall to us, backbone was probably worth it, but also cost us many long days of performance debugging, and we're still not 100% happy with it. For our next project we may try something else.

6 comments

I am surprised by your experience, as there are Backbone projects which have used considerably more objects to no ill effect.

Backbone's three major components, Models/Collections, Views and Events do take some planning to coordinate effectively, but that's part of laying out your application.

Also, using bare JS objects is not an anti-pattern in Backbone. Use Models/Collections when you need to manage data, Views when you need to monitor parts of the DOM, and Events to manage messages between your components. Apply as necessary.

P.S. Model.get is literally a single line of bare JS object property access: http://backbonejs.org/docs/backbone.html#section-38 but if you have a lot of events, or validations conditioned to fire on attribute changes, that may effect how long it takes your setters to run (http://backbonejs.org/docs/backbone.html#section-41 )

Thanks for the note -- the performance problem was in set(), not get (that was lazy of me).

We didn't have a lot of triggers running -- we spent a lot of time looking at performance traces. Just initializing models on page load was incredibly slow. It was particularly bad on a retina iPad.

Backbone's View is incredibly slow and is very ill-suited for views that need 1000+ of them on a single page. The reason is not so much Backbone's code is particularly inefficient but the fact that Backbone.View creates a separate a jQuery context in its constructor, and then delegates events in it, also using jQuery. Both are among the slowest parts of jQuery because they have to go thru Sizzle. So if you have 1000+ of Views, each creating a separate jQuery context of its own, you can easily run up to taking seconds to render a page on Mobile.

On Backgrid (my project), naively creating 1200+ view objects on a Macbook Pro on a 2.4gz i7 takes 700ms. It really does take seconds on mobile.

I'm in the process of getting rid of jQuery and coming up with a performant View class that works more or less like Backbone.View but uses the DOM API directly. Implementing event delegation with straight DOM methods have proven to be troublesome and unreliable so I might need to come up with a different way to attach event handlers on a DOM tree.

Backbone uses jQuery's event delegation, so there should've been minor differences between the two cases you describe, mostly with how listening to the Models/Collections worked.

Additionally, it sounds like you might've been binding a render to a change in the collection? In that case, you'd want to debounce the render or only start listening to changes after the view is actually rendered with data (say the parent only renders that view when it has the data for the 200 cards, then the subview listens for changes on the collection it's given).

Anecdotally, ~1000+ views can be performant in Backbone.

It's hard to say what bottlenecks you were hitting but zombie views that can't be GC'd, rendering to the page thousands of times (instead of to an in memory DOM element), or sorting your collections on dynamic, non-memoized values could have caused those kinds of slowdowns.

Were you using Marionette? It helped me increase performance a lot by cleaning up views properly and organize their rendering optimally. I almost can't imagine using Backbone without Marionette.
I agree with you about not being able to get by without using marionette any more. The funny thing is, that I had to build something without it, to understand why I wanted it in the first place.
Same here. Build a couple of backbone apps and doing my first marionette one. It is much easier and faster working wit marionette.
no, maybe we'll try it.
Did you use Backbone-relational for nested/related models? I've found that it has a significant performance penalty with lots of models.
No we didn't.