title: How to improve performance of single-page application?
body: <p><strong>Introduction</strong><br>
  I have a (mostly) single-page <a href="http://domiy.com" rel="noreferrer">application</a> built with BackboneJS and a Rails backend.</p>
  
  <p>Because most of the interaction happens on one page of the webapp, when the user first visits the page I basically have to pull a ton of information out of the database in one large deeply joined query.</p>
  
  <p>This is causing me some rather extreme load times on this one page.</p>
  
  <p><img src="https://i.stack.imgur.com/o9EgE.png" alt="load times"></p>
  
  <p>NewRelic appears to be telling me that most of my problems are because of 457 individual fast method calls.</p>
  
  <p><img src="https://i.stack.imgur.com/tKH0C.png" alt="fast methid calls"></p>
  
  <p>Now I've done all the eager loading I can do (I checked with the <a href="https://github.com/flyerhzm/bullet" rel="noreferrer">Bullet gem</a>) and I still have a problem.</p>
  
  <p>These method calls are most likely ocurring in my <a href="https://github.com/nesquena/rabl" rel="noreferrer">Rabl</a> serializer which I use to serialize a bunch of JSON to embed into the page for initializing Backbone. You don't need to understand all this but suffice to say it could add up to 457 method calls.</p>
  
  <pre><code>object @search
  attributes :id, :name, :subscription_limit
  
  # NOTE: Include a list of the members of this search.
  child :searchers =&gt; :searchers do
    attributes :id, :name, :gravatar_icon
  end
  
  # Each search has many concepts (there could be over 100 of them).
  child :concepts do |search|
    attributes :id, :title, :search_id, :created_at
  
    # The person who suggested each concept.
    child :suggester =&gt; :suggester do
      attributes :id, :name, :gravatar_icon
    end
  
    # Each concept has many suggestions (approx. 4 each).
    node :suggestions do |concept|
      # Here I'm scoping suggestions to only ones which meet certain conditions.
      partial "suggestions/show", object: concept.active_suggestions
    end
  
    # Add a boolean flag to tell if the concept is a favourite or not.
    node :favourite_id do |concept|
      # Another method call which occurs for each concept.
      concept.favourite_id_for(current_user)
    end
  end
  
  # Each search has subscriptions to certain services (approx. 4). 
  child :service_subscriptions do
    # This contains a few attributes and 2 fairly innocuous method calls.
    extends "service_subscriptions/show"
  end
  </code></pre>
  
  <p>So it seems that I need to do something about this but I'm not sure what approach to take. Here is a list of potential ideas I have:</p>
  
  <p><strong>Performance Improvement Ideas</strong></p>
  
  <p>Dumb-Down the Interface<br>
  Maybe I can come up with ways to present information to the user which don't require the actual data to be present. I don't see why I should absolutely need to do this though, other single-page apps such as <a href="http://trello.com" rel="noreferrer">Trello</a> have incredibly complicated interfaces.</p>
  
  <p>Concept Pagination<br>
  If I paginate concepts it will reduct the amount of data being extracted from the database each time. Would product an inferior user interface though.</p>
  
  <p>Caching<br>
  At the moment, refreshing the page just extracts the entire search out of the DB again. Perhaps I can cache parts of the app to reduce on DB hits. This seems messy though because not much of the data I'm dealing with is static.</p>
  
  <p>Multiple Requests<br>
  It is technically bad to serve the page without embedding the JSON into the page but perhaps the user will feel like things are happening faster if I load the page unpopulated and then fetch the data.</p>
  
  <p>Indexes<br>
  I should make sure that I have indexes on all my foreign keys. I should also try to think about places where it would help to have indexes (such as favourites?) and add them.</p>
  
  <p>Move Method Calls into DB<br>
  Perhaps I can cache some of the results of the iteration I do in my view layer into the DB and just pull them out instead of computing them. Or I could sync things on write rather than on read.</p>
  
  <p><strong>Question</strong><br>
  Does anyone have any suggestions as to what I should be spending my time on?</p>