使用activerecord如何停止内存抖动

时间:2014-12-18 03:58:08

标签: ruby-on-rails ruby

如何在创建一组新对象时重用活动记录对象。

以下面的代码为例:

loop do
  foo = Foo.new
  foo.bar = 'value'
  foo.save!
end

这会导致ruby每次调用Foo.new时都会分配一个新对象。这很慢,并将GC刺入心脏。

有没有一种方法我可以像这样使用foo对象(在这种情况下.reset被错误地使用)

foo = Foo.new
loop do
  foo.reset
  foo.bar = 'value'
  foo.save!
end

因此,通过将对象多次插入数据库而不是在内存中创建新对象来复制对象。

更完整的用例是将数据从消息队列中拉出来。

queue.subscribe do |data|
  foo = Foo.new
  foo.data = data
  foo.save!
end

2 个答案:

答案 0 :(得分:2)

我不想说没有,但是没有办法做到这一点并继续关注Active Record pattern ,这是Rails'引擎盖下的原则ActiveRecord的。正如维基百科文章所述:

  

对象实例绑定到表中的单行

从中您可以看出,您无法将单个对象映射到多个不同的行。

滑轨' ActiveRecord对象有两种不同的形式,看起来很相似,但内部工作方式不同:

  • 非持久对象newassociation.build以及其他一些人的结果)
    他们还没有id,他们还没有效果" Active Records",这意味着在保存时会创建数据库中的新行并且对象是从那一刻起就被认为是持久的。
  • 持久对象(以任何方式从数据库接收)
    一个对象被认为是数据库中的有效行而没有大多数含义。在RDBMS的上下文中,对该对象的任何操作都应该是合理的。

那就是说,为了做到这一点,你必须深入研究AR实施的深度,因为" unpersist" AR对象(如果您遵循该模式),您必须从数据库中删除它。当前AR的实施没有例外。

这是一个小实验。一旦我们拥有一个未经存在的对象,我们就可以对其进行检查,并发现其id等于nil。现在让我们获取一个持久化对象并执行此操作:

# assume we did `t = Thing.first` before
t.id = nil
t.save!

创建一个新对象?没有!更新现有的!

UPDATE `things` SET `id` = NULL WHERE `things`.`id` = 1

当然,数据库拒绝此查询,因为在RDBMS方面将任何记录的主键设置为NULL是不合理的:

Column 'id' cannot be null

为什么呢?见this question。简而言之,那是因为NULL != NULL

答案 1 :(得分:0)

foo = [Foo.new, bar: []]
// and foo[0] is the Foo.new object 
loop do
  foo.bar.pop()
  foo.bar.push('value')
end

我认为你的代码有点过分了,你应该给我们更多信息,但这就是我存储Foo对象和更改foo.bar值的方法,并且从不创建新数组或导致内存泄漏