【问题标题】:Arel::Table @aliases memory leak when used in Rails 5在 Rails 5 中使用 Arel::Table @aliases 内存泄漏
【发布时间】:2017-01-20 11:36:58
【问题描述】:

一句话总结问题:什么会导致Arel::Table@aliases数组在每次使用ActiveRecord完成的搜索中都变大?

我使用 Rails 5 编写了一个简单的 Web 应用程序。当我对其进行负载测试时,内存使用量无限增加。在 220 万次请求之后,进程的常驻内存大小达到了大约 1GB。

我通过在执行 100,000 个请求的负载测试之前、之后和 10 分钟后获取堆转储来进行调查。我使用the heap dump diffing tool found here 分析了堆转储。它说Arel::Table#alias() 创建了大约 398,000 个泄露的对象。

这句话似乎是罪魁祸首:

@aliases << node

通过在我安装的Arel::Table#alias() 版本中添加对uniq! 的调用,我确认Arel::Table@aliases 数组是内存泄漏的根源:

def alias name = "#{self.name}_2"
  Nodes::TableAlias.new(self, name).tap do |node|
    @aliases << node
  end
  @aliases.uniq! # locally added this line
end

通过对 Arel 的此修改,我的应用的内存使用量在负载测试期间保持不变。

据我所知,@aliases 会随着对我的应用程序的每个请求而增长,并且会随着相同的对象而增长。我想知道这是否是 Arel 中的错误,或者我在我的应用程序中做了一些坏事,导致这个数组在没有被清除或垃圾收集的情况下增长。

该应用有四个模型:

模型

class DeviceVendor < ApplicationRecord
end

class Group < ApplicationRecord
end

class RadiusDevice < ApplicationRecord
  belongs_to :device_vendor
  validates :ipv4_address, :ip => {format: :v4}
end

class RadiusVsa < ApplicationRecord
  belongs_to :group
  belongs_to :device_vendor
end

迁移

class CreateGroups < ActiveRecord::Migration[5.0]
  def change
    create_table :groups do |t|
      t.string :dn
      t.integer :rank

      t.timestamps
    end
  end
end

class CreateDeviceVendors < ActiveRecord::Migration[5.0]
  def change
    create_table :device_vendors do |t|
      t.string :name

      t.timestamps
    end
  end
end

class CreateRadiusDevices < ActiveRecord::Migration[5.0]
  def change
    create_table :radius_devices do |t|
      t.string :ipv4_address
      t.string :model_number
      t.belongs_to :device_vendor, index: true, foreign_key: true

      t.timestamps
    end
  end
end

class CreateRadiusVsas < ActiveRecord::Migration[5.0]
  def change
    create_table :radius_vsas do |t|
      t.string :radius_attributes
      t.belongs_to :device_vendor, index: true, foreign_key: true
      t.belongs_to :group, index: true, foreign_key: true

      t.timestamps
    end

  end
end

我唯一的 HTTP 端点根据 Group.dnRadiusDevice.ipv4_address 的输入参数搜索 RadiusVsa。以下是所涉及的 ActiveRecord 调用:

# groups param value is like: ['ou=foo,cn=bar', 'ou=baz,cn=qux']
group = Group.order(rank: :desc).find_by!(dn: params.require('groups'))
# source param value is like: '10.0.0.1'
radius_device = RadiusDevice.find_by!(ipv4_address: params.require('source'))
# RadiusVsa.find_by! is the call that causes Arel::Table#alias() to be invoked
vendor_attributes = RadiusVsa.find_by!(group: group, device_vendor: radius_device.device_vendor)

【问题讨论】:

    标签: ruby-on-rails ruby memory-leaks arel


    【解决方案1】:

    事实证明,这种内存泄漏是 Arel 中的一个错误。在一天没有收到任何回复后,我们创建了 an issue in Rails,现已修复。

    【讨论】:

      猜你喜欢
      • 2012-03-04
      • 2012-08-15
      • 2019-07-02
      • 1970-01-01
      • 2014-01-13
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多