You are on page 1of 3

Ruby on Rails 性能优化的 10 大建议

Ruby On Rails 项目的性能受很多因素的影响,特别是部署服务器的配置。然而程序代码还


是会带来很大不同甚至是决定了你的站点响应速度的快慢。这篇短文介绍了一些关于在
Rails 中对提升性能有很大好处的编码经验,不讨论复杂的关于优化服务器配置方面的内容。
1、优化你的 Ruby 代码。这一点说起来显而易见,但是 Rails 程序在运行时本质上都是 Ruby
代码,所以要确信你的代码从 Ruby 的角度来说是有高效的。对你的代码进行一下回顾,看
看是否需要做一些重构,要不断进行性能和算法效率的考虑。当然性能测试工具对检测较慢
代码是非常有用的,不过下面所列的几项是通常要考虑到的(其中有几项可能对你们来说
已经是常识了)。
1> 如果有可能的代码或者插件,就不必自己再去写了。
2> 在需要转换和处理大文本的时候,用正则表达式要好过用循环判断。
3> 处理 XML 文档用 Libxml 库,性能优于 REXML.
4> 有时你需要为了速度尽量减少一些优雅抽象的编码方式 (比如 define_method 和 yield 是比
较耗资源的。)
5> 解决循环语句缓慢问题的最好办法,就是只要有可能就去掉它们。有时候在一切情况下
你是可以通过重构代码来避免使用循环的。
6> if/unless 语句应尽量简单化并且减少这样的语句,相应的记住 ||= 操作符是你编码时的
朋友。
7> Hash 是昂贵的数据结构。要是你需要不断重复调用一个值可以将其存在一个局部变量里。
更普遍来说,好的方式是把经常要访问到的数据存在变量里(局部,实例或者是类变量)。

2.缓存是好的:缓存能够大幅度地为应用程序加速。可以分几个方面来做:
1> 使用 acts_as_cached 或者 cached_model 组建来缓存模型对象。
2> 使用 MemCacheStore 作为 Session 容器。
3> 通过片段缓存来保存页面(可参考 extended_fragment_cache)。

3、充分发挥数据库的威力是铁律。不要拒绝使用数据库提供的很多很酷的功能,即使它们不
是由 Rails 直接提供或者是通过 ActiveRecord 来实现的。例如,定义一些存储过程和函
数,就可以通过驱动来使用它们直接进行数据库的相关操作,这 要好过于在
ActiveRecord 中定义的高层次的方法。这样会大大提高在 Rails 程序中操作数据的性能。

4、Finders(查找)是超级有用的但是要小心使用。finders 使用起来是让人愉快的,让你能容易
地写出可读性高的代码,并 且还不需要有深入的 SQL 知识。但是易用友好的高层次抽象
化就带来了更多的消耗,在使用时可依据以下几个主要的原
则:
1> 只获取需要的数据。选择语句中读取一些不是真正需要的数据会浪费处理时间。在使用
各种查询时要确定使用了正
确的参数,在:select 参数中指定真正要读取的字段,如果仅仅需要在数据集中读取一定数
量的记录,可以适当地加以
限制(使用:limit 和:offset 属性).
2> 不要让过多的查询把数据库挂掉了,要使用 include 属性来做关联查询。
# 这将只产生一个查询,
# rather than Post.count + 1 queries
for post in Post.find(:all,
:include => [ :author, :comments ])
# Do something with post
end
3> 避免使用类似 MyModel.find_by_*这样的动态查询。使用 User.find_by_username 这样的
语句可读性高并且容易,但是
也带来多一些的消耗。事实上,ActiveRecord 是在 method_missing 中动态生成这些方法的,
所以会比较慢。实际上被定 义和调用的方法,还有在模型类中做的属性映射,最终都
会转化成一个查询语句然后发送给数据库。所以直接使用
MyModel.find_by_sql 或者 MyModel.find 会带来更高的效率。
4> 无论什么时候最优化的 SQL 查询都是使用 MyModel.find_by_sql。不言自明的,即使最
终的查询语句是一样的,使用 find_by_sql 要比 find 更有效率(因为无需将赋给方法的
各种属性参数转换成 SQL 语句)。如果你正在构建一个跨平台使
用的插件,那需要确认所有的 SQL 能够在 Rails 支持的各种数据库上正确执行,或者就要
用 find 方法来替换。一般来说,
用 find 方法有更好的可读性和可维护性,所以在开始用 find_by_sql 对应用做重构前,需
要做些评测和区分哪些查询
较慢需要手工做优化。

5、将一组操作放在一个事务里:ActiveRecord 会将创建和更新记录的操作封装在一个事务
里,多个插入操作会产生多个
事务(每个插入操作一个事务)。把多个插入操作放在一个事务中处理会提升速度。
原代码:
my_collection.each do |q|
Quote.create({:phrase => q})
end
优化后:
Quote.transaction do
my_collection.each do |q|
Quote.create({:phrase => q})
end
end
或者让任何一次插入操作失败都回滚,这样写:
Quote.transaction do
my_collection.each do |q|
quote = Quote.new({:phrase => q})
quote.save!
end
end

6、控制好你的控制器:过滤器是昂贵的,不要滥用它们。并且,也不用过度使用实例变量,
如果不是被视图所需要的.
7、在视图中多使用 HTML.在视图模板里不要过多使用 helper,每次用 helper 构建页面都会
带来额外的步骤。我们是不是
真的需要使用 helper 的方法来生成一个链接的 html,或者是一个文本框或者表单呢? (这
会让对 ruby 不熟悉的页面设
计者开心的。)

8、日志记录:对应用进行配置只记录真正有用的信息。日志是消耗很大的操作,配置不当的
日志记录级别(例如
Logger::DEBUG)会影响产品模式下应用的性能。
9、打 GC 补丁:对,不是一个真正的代码发布版本,而是针对 Ruby 的垃圾回收做一个高效
的优化补丁,这将较大地提升
Rails 的速度。
10、最后一条:我不提倡过早地做性能优化,如果可能,先对这些优化原则有个意识 (但不
要做得过度).

You might also like