每次在同一个控制器中使用时,是否重新计算实例变量?

时间:2015-02-13 22:27:16

标签: ruby-on-rails ruby performance ruby-on-rails-4

我在控制器中定义了三个实例变量。最后两个使用第一个的值。每次第一个用于计算另一个变量时,是否必须重新计算?


换句话说,哪种方法更快?

方法1

def show
  @things = Thing.all.where(boolean: true)
  @things_decreasing = @things.reverse
  @things_random = @things.shuffle
end

方法2

def show
  @things = Thing.all.where(boolean: true)
  @things_decreasing = Thing.all.where(boolean: true).reverse
  @things_random = Thing.all.where(boolean: true).shuffle
end

2 个答案:

答案 0 :(得分:4)

两种方法的性能几乎相同,因为Thing.all.where(boolean: true)会返回ActiveRecord::Relation的实例。 ActiveRecord::Relation不会立即执行数据库查询,而是在需要数据的第一个方法调用(此示例中为reverse)上执行。

方法2创建新的(但相似的)关系对象,而方法1重用相同的关系对象。性能几乎相同,因为与运行多个数据库调用相比,创建该关系的速度非常快,并且两个示例都有相同数量的数据库调用。

但是有一种方法可以加快速度:示例中的两个方法只执行一次数据库调用,因为Rails在数据库连接器中缓存数据库调用。但是Rails会重新生成缓存数据库对每个查询的响应结果,并且每次都会返回一个包含新实例的新数组。

将所有对象加载到数组中并重用该数组可能会更快(取决于数据库响应的大小):

def show
  # triggers the database call and returns an array (not a Relation)
  @things = Thing.where(boolean: true).to_a 

  # re-use the result from the @things array, and not a Relation object
  @things_decreasing = @things.reverse
  @things_random     = @things.shuffle
end

答案 1 :(得分:0)

@things = Thing.where(boolean: true).to_a  
Benchmark.measure{@things_decreasing = @things.reverse}

使用Benchmark可以检查性能时间。为了提高性能,最好使用返回的数组。