哈希中的 ActiveRecord 对象不会被垃圾收集——是错误还是某种缓存功能?

2024-02-27

我有一个简单的 ActiveRecord 模型,名为Student表中有 100 条记录。我在 Rails 控制台会话中执行以下操作:

ObjectSpace.each_object(ActiveRecord::Base).count
# => 0

x = Student.all

ObjectSpace.each_object(ActiveRecord::Base).count
# => 100

x = nil
GC.start

ObjectSpace.each_object(ActiveRecord::Base).count
# => 0     # Good!

现在我执行以下操作:

ObjectSpace.each_object(ActiveRecord::Base).count
# => 0

x = Student.all.group_by(&:last_name)

ObjectSpace.each_object(ActiveRecord::Base).count
# => 100

x = nil
GC.start

ObjectSpace.each_object(ActiveRecord::Base).count
# => 100     # Bad!

谁能解释为什么会发生这种情况,以及是否有一种聪明的方法可以在不知道底层哈希结构的情况下解决这个问题?我知道我可以这样做:

x.keys.each{|k| x[k]=nil}
x = nil
GC.start

它会正确地从内存中删除所有 Student 对象,但我想知道是否有一个通用的解决方案(我的现实生活中的问题很广泛,并且具有比上面显示的哈希更复杂的数据结构)。

我正在使用 Ruby 1.9.3-p0 和 Rails 3.1.0。

更新(已解决)

根据下面 Oscar Del Ben 的解释,在有问题的代码片段中创建了一些 ActiveRecord::Relation 对象(它们实际上是在两个代码片段中创建的,但由于某种原因,它们仅在第二个代码片段中“行为不当”。有人可以阐明一下吗?为什么?)。它们通过名为@records 的实例变量维护对ActiveRecord 对象的引用。可以通过 ActiveRecord::Relation 上的“reset”方法将该实例变量设置为 nil。您必须确保对所有关系对象执行此操作:

ObjectSpace.each_object(ActiveRecord::Base).count
# => 100

ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset)

GC.start
ObjectSpace.each_object(ActiveRecord::Base).count
# => 0

注意:您还可以使用 Mass.detach (使用红宝石质量 https://github.com/archan937/ruby-massgem Oscar Del Ben 引用),尽管它会比上面的代码慢得多。请注意,上面的代码不会从内存中删除一些 ActiveRecord::Relation 对象。不过,这些似乎微不足道。你可以尝试这样做:

Mass.index(ActiveRecord::Relation)["ActiveRecord::Relation"].each{|x| Mass.detach Mass[x]}
GC.start

这将删除一些 ActiveRecord::Relation 对象,但不是全部(不知道为什么,剩下的那些没有 Mass.references。奇怪)。


I think I know what's going on. Ruby's GC wont free immutable objects (like symbols!). The keys returned by group_by are immutable strings, and so they wont be garbage collected.

UPDATE:

看来问题不在于 Rails 本身。我尝试单独使用 group_by ,并且有时这些对象不会被垃圾收集:

oscardelben~/% irb
irb(main):001:0> class Foo
irb(main):002:1> end
=> nil
irb(main):003:0> {"1" => Foo.new, "2" => Foo.new}
=> {"1"=>#<Foo:0x007f9efd8072a0>, "2"=>#<Foo:0x007f9efd807250>}
irb(main):004:0> ObjectSpace.each_object(Foo).count
=> 2
irb(main):005:0> GC.start
=> nil
irb(main):006:0> ObjectSpace.each_object(Foo).count
=> 0
irb(main):007:0> {"1" => Foo.new, "2" => Foo.new}.group_by
=> #<Enumerator: {"1"=>#<Foo:0x007f9efb83d0c8>, "2"=>#<Foo:0x007f9efb83d078>}:group_by>
irb(main):008:0> GC.start
=> nil
irb(main):009:0> ObjectSpace.each_object(Foo).count
=> 2 # Not garbage collected
irb(main):010:0> GC.start
=> nil
irb(main):011:0> ObjectSpace.each_object(Foo).count
=> 0 # Garbage collected

我已经深入研究了 GC 的内部结构(非常容易理解),这似乎是一个范围问题。 Ruby 遍历当前范围内的所有对象并标记它认为仍在使用的对象,然后遍历all堆中的对象并释放那些已存在的对象not已被标记。

在这种情况下,我认为哈希值仍然被标记,即使它超出了范围。发生这种情况的原因有很多。我会继续调查。

更新2:

我找到了保存对象引用的内容。为此,我使用了红宝石质量 https://github.com/archan937/ruby-mass宝石。事实证明,Active Record 关系跟踪返回的对象。

User.limit(1).group_by(&:name)
GC.start
ObjectSpace.each_object(ActiveRecord::Base).each do |obj|
  p Mass.references obj # {"ActiveRecord::Relation#70247565268860"=>["@records"]}
end

不幸的是,打电话reset关于这种关系似乎没有帮助,但希望目前这些信息已经足够了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

哈希中的 ActiveRecord 对象不会被垃圾收集——是错误还是某种缓存功能? 的相关文章

  • 随机显示 NoMethodError:未定义的方法“空?”对于 0:Fixnum

    它在我的本地计算机上运行良好 但使用 Puma Web 服务器在 Heroku 上的rails admin 中出现以下错误 这是我使用 enumerize 的方式 enumerize date type in last date 0 beg
  • Base36 编码字符串?

    我一直在网上查找 但找不到解决此问题的方法 在 Python Ruby 或 Java 中 如何对以下字符串进行 Base 36 编码 nOrG9Eh0uyeilM8Nnu5pTywj3935kW 5 Ruby 以 36 为基数 s unpa
  • Rails 未定义“2013-03-06”的方法“strftime”:字符串

    我收到错误 2013 03 06 的未定义方法 strftime 字符串 当尝试使用 strftime 从字符串 2013 03 06 正常显示日期 2013 年 6 月星期日 3 日或类似的日期 时 在我的 index html erb
  • 从标签中提取 HTML5 数据属性

    我想从标签中提取所有 HTML5 数据属性 就像这个 jQuery 插件 http www orangesoda net jquery dataset html 例如 给定 span class highlight Joe Bloggs s
  • Ruby on Rails 中的垃圾收集器?

    我尝试在 Google 上搜索很多有关 Rails 垃圾收集器的信息 但没有得到可靠的答案 有谁有资源来展示如何垃圾收集是在 Rails 中实现的吗 我们怎样才能控制它呢 Rails 是一个框架 而不是一种语言 Rails 背后的语言称为
  • mail_form gem 与 sidekiq 工作者

    怎么做邮件表格gem 与 sidekiq 工作人员一起工作吗 https github com plataformatec mail form https github com plataformatec mail form 我可能做错了什
  • Array.find方法问题

    我在 ZenTest 源代码中找到这一行 result test mappings find file re ignored filename file re The test mappings and result这里都是 Array 对
  • 核心中的 find_by() 和 FinderMethods 中的 find_by() 有什么区别?

    目前我正在开发一个 gem 它会覆盖 ActiveRecordswhere 通过研究 我偶然发现了两种不同的find by实施 一个是在core https github com rails rails blob 5 0 stable ac
  • Rails 中的代码片段应该放在哪里?

    我有这个代码片段 可以为 POST 生成签名 它的细节并不重要 但我想知道的是 由于它不是与模型相关的代码块 所以它确实可以在任何地方使用 在控制器中 在模型中 在视图助手中 即使在视图中 因此 我不确定在哪里 甚至更大的问题是 一旦将其放
  • 帮助重构这个讨厌的 Ruby if/else 语句

    所以我有这个大而多毛的 if else 语句 我将跟踪号码传递给它 然后它确定它是什么类型的跟踪号码 我怎样才能简化这件事 具体来说就是想减少代码行数 if num length lt 8 tracking service false el
  • 如何在 Ruby 2.0 中使用调试器?

    我知道调试器 gem 不会也永远不会与 ruby 2 0 per 兼容正式支持ruby 2 X https github com cldwalker debugger issues 47 issuecomment 44027702 Ruby
  • 在 cygwin 和 powershell 中查看不同的 gem 列表

    我用的是gem listpowershell 和 cygwin 中的命令都显示不同的 gem 列表 Cygwin 显示 LOCAL GEMS bundler 1 2 3 json 1 7 5 minitest 2 12 1 rake 0 9
  • 未找到 Gem 命令

    我已经在 Ubuntu 10 10 32 位上安装了 gem apt get install gem y 但当我尝试跑步时 gem install something gem 我收到未找到命令的错误 bash gem command not
  • 设计涟漪

    我正在尝试使用以 riak 作为数据库的设备创建身份验证 我找到了同样的 ORM 策略https github com frank06 devise ripple https github com frank06 devise ripple
  • 匿名监听器与弱引用不兼容吗?

    我正在阅读刚刚被问到的这个问题 避免回调中的内存泄漏 https stackoverflow com questions 8475314 我很困惑 直到有人回答了以下问题 这种方法的问题是你不能拥有一个仅在集合中引用的侦听器 因为它会随机消
  • to_proc 方法在 Ruby 中意味着什么?

    我正在学习 Rails 并关注这个线程 https stackoverflow com questions 1961030 我被困住了to proc方法 我认为符号只是字符串的替代品 它们就像字符串 但在内存方面更便宜 如果我还缺少任何其他
  • Ruby 多维数组

    也许只是我缺乏在这里找到东西的能力 这就是问题所在 但我找不到任何关于如何在 Ruby 中创建多维数组的信息 有人可以给我一个如何做的例子吗 严格来说 在 Ruby 中创建多维数组是不可能的 但是可以将一个数组放入另一个数组中 这与多维数组
  • 与 Array 相比,使用 Ruby NArray 有哪些优点?

    我刚刚遇到了 Ruby 的 NArray 库 请原谅我在问这个问题时的无知 与标准 Ruby Array 实现相比 使用 NArray 库有哪些优点 我已经看到 NArray 是面向数值计算的 但是看看 API 看起来好像只有一些针对数值的
  • 回形针:从带扩展名的 url 上传

    我想通过 S3 存储上的回形针从 URL 上传图片 我与 Ruby 1 9 3 Rails 3 2 6 paperclip 3 1 3 aws sdk 1 3 9 我有我的图片模型 class Asset has attached file
  • 并行 Haskell - GHC GC 火花

    我有一个正在尝试并行化的程序 带有可运行代码的完整粘贴here http lpaste net 101528 我进行了分析 发现大部分时间都花在findNearest这本质上是一个简单的foldr超过一个大Data Map findNear

随机推荐

  • 反射应该使用到什么程度?

    我们在项目中遇到了一个非常棘手的场景 我们在项目中使用了很多反射 我们有 由属性和反射驱动的验证框架 使用属性和反射将 DataRow 转换为实体对象的扩展方法 反之亦然 我们对 DataTable 和 EntityCollections
  • 统计PHP页面中所有HTML标签

    我花了时间在正则表达式上解决这个问题但没有结果 我尝试使用 PHP 5 3 解决这个问题 诸如 在页面中重复的次数以及有关页面中所有标签的信息等信息 不幸的是 您的问题目前的形式几乎无法理解 请尝试更新并更具体 如果你想计算页面中所有 HT
  • Intl.DateTimeFormat 选项哈希:使用“2 位数字”获取前导零

    Intl DateTimeFormat en US weekday long year numeric month long day 2 digit hour 2 digit minute 2 digit second 2 digit fo
  • 如何使用 d3.js 将填充部分添加到 SVG 圆圈

    我正在使用 d3 js 生成一些 SVG 圆圈 我能够生成它们 但我不知道如何将它们分成 4 个相等的部分并为每个部分填充颜色 我正在使用 d3 js 版本 4 这是我的小提琴中的 javascript 片段 var nodes type
  • 无法通过curl或Postman访问docker url

    我可以使用以下路径在浏览器中访问我的网站 my dash docker localhost 8000 我正在尝试编写一个API端点 但无法通过Postman或curl访问该网站 curl my dash docker localhost 8
  • 将数据存储到 DOM - 元素值与数据属性

    要将值存储在 DOM 元素中 我们可以通过data属性 abc data item 1 检索做 abc data item 但今天我了解到我们也可以这样做 abc 0 item 1 检索做 abc 0 item 它们之间有什么区别 哪一个更
  • Python 多线程在 IO 任务中没有任何好处?

    我正在尝试用 python 读取数千小时的 wav 文件并获取它们的持续时间 这本质上需要打开 wav 文件 获取帧数并考虑采样率 下面是代码 def wav duration file name wv wave open file nam
  • uitableviewcell 上的 tableview 中出现重复行

    我发现一些帖子与我的问题相似但不完全相同 在我的应用程序中 用户可以在多个 uitableviews 之间导航以深入了解所需的结果 当用户向前 然后向后 然后向前等时 可以注意到行正在被重绘 重写 并且文本变得越来越粗 我发现在一些帖子中这
  • 如何将函数参数传递给 boost::thread_groups::create_thread()

    我是新来的增强线程我试图了解如何将函数参数传递给boost thread groups create thread 功能 在阅读了一些教程和 boost 文档后 我了解到可以简单地将参数传递给这个函数 但我无法让这个方法起作用 我读到的另一
  • 使用 BigQuery 的 QUALIFY 运算符有什么优势?

    我刚刚发现了 BigQuery 的 QUALIFY 运算符 并且一直在以下位置阅读相关内容 https cloud google com bigquery docs reference standard sql query syntax q
  • 如何使用react-google-recaptcha重置Google recaptcha

    看起来谷歌验证码的工作方式是这样的 如果使用特定令牌进行了验证尝试 则无法再次使用它 文档指出 您将需要调用 grecaptcha reset 来要求最终用户再次使用 reCAPTCHA 进行验证 我正在尝试使用react google r
  • Objects.hash() 与 Objects.hashCode(),需要澄清

    从 Java 7 开始 我们有 o hashCode Objects hashCode o Objects hash o 前两个与空检查大致相同 但最后一个是什么 当提供单个对象引用时 返回值不会 不等于该对象引用的哈希码 这是为什么 我的
  • 避免嵌套查询

    避免嵌套查询是多么重要 我总是学会像躲避瘟疫一样避开它们 但它们对我来说是最自然的事情 当我设计查询时 我首先编写的是嵌套查询 然后我将其转换为联接 这有时需要花费很多时间才能正确 并且很少会带来很大的性能提升 有时确实如此 那么他们真的那
  • 将 (Boost) Asio 与 Android NDK 结合使用的限制

    目前在 Android 平台上将 Asio 与 NDK 结合使用有哪些限制 除了 Asio 还有其他你肯定会选择的选择吗 因此没有限制 唯一令人担忧的是缺乏官方支持 你必须构建升压库 参考我的帖子https stackoverflow co
  • 滚动视图不起作用 IOS 7

    我有一个滚动视图 其中有 20 个 UItextview 滚动视图不起作用 我在 viewdidload 中设置了以下内容 self MainScroll contentSize CGSizeMake 320 1800 它仍然不滚动 但是
  • Pip 出现问题,缺少已安装的模块?

    我已经重新安装了 python packaging 并且出现了这个 pip help Traceback most recent call last File usr bin pip line 6 in
  • 在 Emacs 中编写 HTML5?

    在 Emacs 中编写 HTML5 的最佳解决方案是什么 是否有一种模式可以进行一致性检查 我最好的建议是使用nxml 模式 http www thaiopensource com nxml mode 如果您使用该平台 则可以在多个 Lin
  • 从 GitHub 删除电子邮件也会删除提交

    我有 2 封与我的 Github 帐户关联的电子邮件 一封是主电子邮件 另一封是辅助电子邮件 当我从帐户中删除辅助电子邮件时 几乎一半的提交都消失了 删除辅助电子邮件地址时如何保留我的提交 None
  • 如何在 Powershell 中发出经过身份验证的 Web 请求?

    在 C 中 我可能会这样做 System Net WebClient w new System Net WebClient w Credentials new System Net NetworkCredential username au
  • 哈希中的 ActiveRecord 对象不会被垃圾收集——是错误还是某种缓存功能?

    我有一个简单的 ActiveRecord 模型 名为Student表中有 100 条记录 我在 Rails 控制台会话中执行以下操作 ObjectSpace each object ActiveRecord Base count gt 0