5

简介我有一个(大部分)用 BackboneJS 和 Rails 后端构建的
单页应用程序。

因为大部分交互发生在 webapp 的一个页面上,当用户第一次访问该页面时,我基本上必须在一个大型深度连接查询中从数据库中提取大量信息。

这导致我在这一页上的加载时间相当长。

加载时间

NewRelic 似乎在告诉我,我的大部分问题是由于 457 个单独的快速方法调用造成的。

快速方法调用

现在我已经完成了我能做的所有急切加载(我检查了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 )具有非常复杂的界面。

概念分页
如果我对概念进行分页,它将减少每次从数据库中提取的数据量。虽然会产生劣质的用户界面。

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

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

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

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

问题
有人对我应该把时间花在什么方面有任何建议吗?

4

2 回答 2

1

我建议将您的 JS 代码库分离为使用RequireJS之类的资产加载器动态加载的模块。这样你就不会在加载时触发这么多 XHR。

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

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

于 2012-05-05T16:46:07.857 回答
1

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

最重要的是,听起来您的问题并不真正出在客户端 - 听起来您的服务器端代码正在减慢速度,所以我会探索您可以采取哪些措施来获取更少的数据,或者推迟复杂的查询,直到它们确实需要。

于 2012-05-05T21:45:43.437 回答