提高 Rails 视图渲染的性能
Posted
技术标签:
【中文标题】提高 Rails 视图渲染的性能【英文标题】:improving performance of rails view rendering 【发布时间】:2012-06-18 01:55:19 【问题描述】:我有一个电子商务 Rails 应用程序,出于报告原因,我们需要在其中输出客户在过去一年内在页面上下的订单。现在,数据集非常大,在单个页面上显示这些订单需要相当多的 SQL 处理。这个任务最初很慢,因此我将所有需要的订单详细信息移到了 Redis 服务器,现在数据获取变得非常快,但我们还没有完全做到。
这就是我们所拥有的:
Rendered **path**/sales_orders.html.haml within layouts/admin (39421.1ms)
Completed 200 OK in 44925ms (Views: 39406.8ms | ActiveRecord: 417.2ms)
应用程序托管在 Heroku 上,如果一个请求超过 30 秒,它就会被终止。正如你所看到的,我们远远超过了这个限制。大部分时间都浪费在渲染视图上。
该页面包含一个日期过滤器,用户可以在其中选择从中选择订单的日期范围。因此,缓存不是理想的解决方案,因为日期范围可能每次都发生变化。
有什么想法可以做到这一点吗?
Redis 键的格式(以下是 Redis 哈希):
orders:2012-01-01:123
orders:yyyy-mm-dd:$order-id
用户只需提供一个日期范围,我就可以在订单命名空间下获得该日期范围内的所有键。
这是我如何从 Redis 订单键中获取客户名称的方法:
= REDIS.hget(order_key, "customer_name")
【问题讨论】:
感谢 Oscar,接受标准之一是不使用分页 好吧,如果标准不是使用分页,那么标准就是它不起作用。对于需要 44 秒渲染的视图,其上必须显示大量数据。这对客户端来说也很困难,因为他们的浏览器必须呈现一个巨大的页面。您能否让我们知道我们在此页面上讨论了多少条记录?另外,您的视图代码是什么样的?我只是认为您不能期望任意大型查询总是快速显示而没有分页或限制。 @MichaelPapile 我完全同意你的看法。一些非技术人员只是提出了奇怪且难以达到的标准。我一直在努力让利益相关者了解这里所涉及的内容。页面上有大约 12,000 条记录,当页面呈现时,我的 Safari 和 Firefox 浏览器半无响应。你是对的! @JasdeepSingh 是的,让非技术人员知道什么是难易是技术中最难的任务! 我意识到这早就过期了,但是对于这样的事情,您似乎可以很好地呈现最初可查看的部分,然后使用 javascript 在屏幕上呈现其他数据页面初始页面加载。不理想,但它至少会将请求分解成更小的部分。 【参考方案1】:考虑使用Heroku Scheduler 插件通过定期任务构建报告。 只要最后一分钟的订单不需要包含在报告中,您就可以每晚构建您的报告并立即下载以与您的早晨咖啡一起阅读,甚至将它们邮寄给您(或任何需要阅读的人)他们。)
如果您需要交互式选择报告时段,则需要将请求排队并使用background jobs 构建报告。
【讨论】:
是的 +1 最好的办法是尽可能预渲染这些文档【参考方案2】:我建议您使用片段缓存。读取片段非常快(约 0.5 毫秒),根据我的经验,通过不一次又一次地重新渲染部分片段,您会看到巨大的加速增益。这也是一个相当便宜的解决方案,因为 Rails 负责使片段无效(如果您将模型用作缓存键的一部分)并且它需要对模板进行最少的更改。 IE。解决方案可以很简单:
<% @orders.each do |order| %>
<% cache ["v1", order] do %>
<%= render order %>
<% end %>
<% end %>
【讨论】:
【参考方案3】:几乎所有的时间都花在了渲染视图上。这可能意味着您有很多部分或其他复杂的视图逻辑。您的一些选择是:
-
为您的输出分页,但为未分页的输出提供 PDF 或 CSV。
简化您的视图逻辑...很多。
尝试使用循环之类的辅助工具,而不是呈现复杂的表格或嵌套的部分。
使用 JSON 和 JavaScript 将您的渲染移至客户端。
就是这样,真的。如果其中一项或多项无法将您带到您需要去的地方,那么可能是时候重新审视您的要求了。
【讨论】:
以上是关于提高 Rails 视图渲染的性能的主要内容,如果未能解决你的问题,请参考以下文章