如何加速Rails 5视图渲染?

3
我有一个Rails 5应用程序,其中包含一个名为Sensor Registry的模型。
目前它有约160,000条记录,但我在尝试显示这些数据时遇到了极低的加载时间。
该应用程序运行在一台双核Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz和2GB RAM的服务器上。
服务器日志显示如下:
开始GET“/sensor_registries”以在2017-01-10 23:43:41 +0000时从187.220.30.180获取
无法从187.220.30.180呈现控制台!允许网络:127.0.0.1,::1,127.0.0.0/127.255.255.255
ActiveRecord :: SchemaMigration Load(1.2ms)SELECT“schema_migrations”。* FROM“schema_migrations”
作为HTML处理SensorRegistriesController#index
在layouts / application中呈现sensor_registries / index.html.erb
SensorRegistry Load(604.0ms)SELECT“sensor_registries”。* FROM“sensor_registries”
Sensor Load(0.6ms)SELECT“sensors”。* FROM“sensors”WHERE“sensors”。id”IN(49,50,51,52,53,54,55,56,57,58,59,60,65,61,63,64,62)
在layouts / application中呈现sensor_registries / index.html.erb(54663.9ms)
完成200 OK,共计55468ms(视图:54827.7ms | ActiveRecord:611.5ms)
我解决了N + 1问题,但我想知道是否有更多关于数据库查询的优化方法。
无论如何,问题似乎出现在渲染页面的时候,它需要大约54秒才能处理完毕。
有没有办法优化CPU使用?
什么是加速处理和快速向用户显示数据的最佳解决方案?

2
这是一个没有具体应用知识很难回答的问题。但是,您需要对您的操作进行分析,并查看您可以改进缓慢部分的地方。像NewRelicRequestProfiler/KCachegrind这样的工具对于这种情况非常有用。 - Chris Heald
1
我只是在想为什么需要显示160k条记录,用户如何在一个有巨大滚动条的页面上查看所有这些记录。 - Milind
你能发布控制器和视图源代码吗? - Zepplock
通常,这是一个与代码相关的问题,您应该检查在视图中是否调用了n+1个查询,或者是否有可以避免重复的代码。 - ErvalhouS
3个回答

5
这显然不像是硬件问题,而是实现问题。如果不了解数据结构和架构,那么无法完美回答。但以下几点建议可能会帮助你找到问题所在:
1)呈现的页面有多大?数据量是否太大导致呈现时间缓慢?如果问题出在此处,可以考虑对结果进行分页。
2)Ruby进程每次使用多少内存?当你说“它大约有160,000条记录”时,我假设你是在谈论sensor_registries表,并且我假设后续的传感器查询中带有sensors.id in (...),该查询是使用sensor_registries表的某些数据构建的。如果在进一步处理之前将整个表加载到内存中,那么Ruby进程是否已经超出了内存限制?
3)此外,真的需要一次性加载整个表吗?你可能需要查看http://apidock.com/rails/ActiveRecord/Batches/find_in_batches。该方法非常适合在大型表上拆分需要完成的工作。

4) 更好的方法是重新思考你的架构。作为同步请求的一部分,将整个表加载到内存中(即使只是一个小表)几乎总是不可取的。你能否想出一种 SQL 查询来获取所有需要的记录而不加载整个表格?

5) 如果你绝对需要整个表格,那么在单次加载后缓存结果怎么样?如果你期望查询结果在具有相同参数的请求之间是相同的,那么你可以使用这些参数构造一个缓存键,并用它来存储结果吗?至少这样,第一个请求之后的所有请求都会更快。


3

使用以下方法:

  • 使用分页功能,每页显示有限数量的记录,并在单击按钮时载入更多记录。
  • 使用页面缓存,将数据放入缓存中,在较短时间内加载重型页面。
  • 在页面加载后加载js文件,并使用压缩的js文件。

遵循DRY原则,让模型更加丰满,控制器更加精简。 - puneet18

1
使用分页或其他方式减少同时显示的记录数量(最多5-10条)。这样可以大大减少查询和呈现的时间。我建议使用will_paginate gem,但还有很多其他选择。
在视图中,减少用于呈现每个传感器的逻辑,并创建单个传感器(show)的单独视图。在单个传感器视图中,您可以添加更多逻辑。
使用新的Relic gem监控您的应用程序,并查看哪些请求需要最长时间。也许您有缓慢的外部资源,如API调用等,可以通过Ajax而不是在服务器上执行:https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-installation 这些是基础知识,完成后,可以继续进行急切加载和缓存。
有关急切加载,请阅读此内容:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

关于缓存,请阅读DHH的博客文章:https://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接