如何提高单页面应用程序的性能?

时间:2012-05-05 09:52:30

标签: ruby-on-rails ruby-on-rails-3 performance backbone.js rabl

简介
我有(主要)单页application使用BackboneJS和Rails后端构建。

由于大多数交互发生在webapp的一个页面上,当用户第一次访问该页面时,我基本上必须从一个大的深度连接查询中提取出大量信息。

这导致我在这一页上有一些相当极端的加载时间。

load times

NewRelic似乎告诉我,我的大部分问题都是因为457个单独的快速方法调用。

fast methid calls

现在我已经完成了所有我可以做的急切加载(我使用Bullet gem检查过)并且我仍有问题。

这些方法调用最有可能出现在我的Rabl序列化程序中,我用它来序列化一堆JSON以嵌入到初始化Backbone的页面中。您不需要了解所有这些,但足以说它可以添加多达457个方法调用。

object @search
attributes :id, :name, :subscription_limit

# NOTE: Include a list of the members of this search.
child :searchers => :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 => :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

所以我似乎需要对此​​做些什么,但我不确定采取什么方法。以下列出了我的潜在想法:

绩效改进理念

愚弄界面
也许我可以想出办法向用户呈现不需要实际数据的信息。我不明白为什么我绝对需要这样做,但Trello等其他单页应用程序的界面非常复杂。

概念分页
如果我对概念进行分页,则每次都会减少从数据库中提取的数据量。产品会是一个劣质的用户界面。

缓存
此时,刷新页面只会再次从DB中提取整个搜索。也许我可以缓存部分应用程序以减少数据库命中。这看起来很混乱,因为我正在处理的数据并不多是静态的。

多次请求
在没有将JSON嵌入到页面中的情况下提供页面在技术上是不好的,但是如果我加载未填充的页面然后获取数据,用户可能会感觉事情发生得更快。

索引
我应该确保我的所有外键都有索引。我还应该尝试考虑哪些地方有助于索引(例如收藏夹?)并添加它们。

将方法调用移入数据库中 也许我可以将我在视图层中进行的迭代的一些结果缓存到数据库中,然后将它们拉出来而不是计算它们。或者我可以在写入时而不是在读取时同步事物。

问题
有没有人对我应该花多少时间有任何建议?

2 个答案:

答案 0 :(得分:1)

我建议将您的JS代码库分成使用RequireJS等资产加载器动态加载的模块。通过这种方式,您无法在加载时触发这么多XHR。

当需要特定模块时,它可以在适当的时间加载和初始化,而不是每次加载页面。

如果您稍微复杂一下代码,每个模块应该能够启动和停止。因此,如果您有任何polling出现或复杂的代码执行,您可以停止模块以提高性能并减少网络负载。

答案 1 :(得分:1)

这是一个难以回答的问题,但却无法看到实际的用户界面,但我会专注于仅显示显示初始界面所需的数据。例如,如果用户必须向下钻取以查看您正在呈现的某些数据,则可以按需加载该数据,而不是将其作为初始有效负载的一部分加载。你提到搜索可以有多达100个“概念”,也许你最初不需要获取所有这些概念?

最重要的是,听起来你的问题确实不在客户端 - 听起来你的服务器端代码正在减慢速度,所以我会探索你可以做些什么来获取更少的数据,或者推迟复杂的查询,直到明确需要它们为止。

相关问题