Ruby on rails 经过一个过程后,为什么Ruby中的内存会一直保持不变?
我将Rails4与Ruby 2.1.0结合使用。我有一个代码,它需要大约2GB的内存来完成这个过程,但问题是在完成这个过程之后…为什么内存使用率仍然在上升 我还将Ruby on rails 经过一个过程后,为什么Ruby中的内存会一直保持不变?,ruby-on-rails,ruby,memory,memory-management,memory-leaks,Ruby On Rails,Ruby,Memory,Memory Management,Memory Leaks,我将Rails4与Ruby 2.1.0结合使用。我有一个代码,它需要大约2GB的内存来完成这个过程,但问题是在完成这个过程之后…为什么内存使用率仍然在上升 我还将nil赋值给使用后的变量,该变量节省了300 MB,但Ruby进程仍使用了大量内存 下面是重现问题的示例代码: def download_data(params, options = {}) $file_name = '' portfolio_names = Portfolio.get_names buildin
nil
赋值给使用后的变量,该变量节省了300 MB,但Ruby进程仍使用了大量内存
下面是重现问题的示例代码:
def download_data(params, options = {})
$file_name = ''
portfolio_names = Portfolio.get_names
building_names = Building.get_names
tenant_names = Tenant.get_names
meter_names = Meter.get_meter_names
@portfolio_info, @building_info, @tenant_info, @meter_id, @from_date, @to_date = params[:portfolio_name], params[:building_name], params[:tenant_name], params[:meter_id], params[:from_date], params[:to_date]
@from_date = DateTime.parse(@from_date).to_i
@to_date = DateTime.parse(@to_date).to_i
@building_f_name = building_names["#{@building_info}"]
unless params[:fields].nil?
@fields = params[:fields].split('_')
@columns = []
@fields.each do |f|
if f.length > 0
@columns << MeterData.new.show_real_value_of_meter_data_field_revert(f).to_sym
end
end
@columns << 'date_time'.to_sym
@columns << 'tenant'.to_sym
@columns << 'meter_id'.to_sym
else
@columns = [:id, :date_time, :w3pht, :whintvlrec, :w__3phmaxavgdmd, :tenant, :meter_id]
end
#### database fetch ###########
@meter_data = MeterData.find_by_sql("SELECT tenant, meter_id, SUM(van) as van, SUM(vbn) as vbn,
SUM(vcn) as vcn, SUM(ia) as ia, SUM(ib) as ib, SUM(ic) as ic,
SUM(w3pht) as w3pht, SUM(pf3pht) as pf3pht, SUM(f) as f,
SUM(whrec) as whrec, SUM(whtot) as whtot, SUM(varhrec) as varhrec,
SUM(varhtot) as varhtot, SUM(whintvlrec) as whintvlrec,
SUM(whintvldel) as whintvldel, SUM(w__phavg) as w__phavg,
SUM(var__3phavg) as var__3phavg, SUM(w_3phavg) as w_3phavg,
SUM(var_3phavg) as var_3phavg, SUM(phai) as phai, SUM(phbi) as phbi,
SUM(phci) as phci, SUM(w__3phmaxavgdmd) as w__3phmaxavgdmd,
MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd_max, SUM(var__3phmaxavgdmd) as var__3phmaxavgdmd,
SUM(w_3phmaxavgdmd) as w_3phmaxavgdmd, SUM(var_3phmaxavgdmd) as var_3phmaxavgdmd,
date_time FROM `meter_data` WHERE (`date_time_i` >= #{@from_date} AND `date_time_i` <= #{@to_date}
AND building = '#{@building_info}') GROUP by tenant, meter_id, date_time
ORDER BY `meter_data`.`date_time_i` ASC")
sleep 0.5
@meter_sum = MeterData.find_by_sql("SELECT meter_id, SUM(van) as van, SUM(vbn) as vbn, SUM(vcn) as vcn,
SUM(ia) as ia, SUM(ib) as ib, SUM(ic) as ic, SUM(w3pht) as w3pht,
SUM(pf3pht) as pf3pht, SUM(f) as f, SUM(whrec) as whrec,
SUM(whtot) as whtot, SUM(varhrec) as varhrec, SUM(varhtot) as varhtot,
SUM(whintvlrec) as whintvlrec, SUM(whintvldel) as whintvldel,
SUM(w__phavg) as w__phavg, SUM(var__3phavg) as var__3phavg,
SUM(w_3phavg) as w_3phavg, SUM(var_3phavg) as var_3phavg,
SUM(phai) as phai, SUM(phbi) as phbi, SUM(phci) as phci,
SUM(w__3phmaxavgdmd) as w__3phmaxavgdmd, MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd_max,
SUM(var__3phmaxavgdmd) as var__3phmaxavgdmd, SUM(w_3phmaxavgdmd) as w_3phmaxavgdmd,
SUM(var_3phmaxavgdmd) as var_3phmaxavgdmd, date_time FROM `meter_data`
WHERE (`date_time_i` >= #{@from_date} AND `date_time_i` <= #{@to_date} AND building = '#{@building_info}')
GROUP by meter_id ORDER BY `meter_data`.`date_time_i` ASC")
@meter_data_max = MeterData.find_by_sql("SELECT tenant, meter_id, MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd,
date_time FROM `meter_data` WHERE (`date_time_i` >= #{@from_date} AND `date_time_i` <= #{@to_date}
AND building = '#{@building_info}') GROUP by tenant, meter_id
ORDER BY `meter_data`.`date_time_i` ASC")
sleep 0.5
@uniq_meter_id = MeterData.select(:meter_id).where("`date_time_i` >= #{@from_date} AND `date_time_i` <= #{@to_date} AND building = '#{@building_info}'").uniq(:meter_id)
#### database fetch ###########
p = Axlsx::Package.new
wb = p.workbook
wb.styles do |s|
styles_hash = AxlsxStylesHash.get s
wb.add_worksheet(:name => "Building data details") do |sheet|
$row_num = 0
meter_extra = MeterExtra.new
columns_ = []; @columns.each { |s| columns_ << "#{s}_".to_s }
sheet.add_row []
$row_num += 1
sheet.add_row ["Building report of #{@building_f_name} #{@from_date} to #{@to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A2:Q2")
new_columns_ = []
new_columns_ << "Date & Time" if columns_.include?('date_time_')
new_columns_ << "Building" if columns_.include?('building_')
new_columns_ << "Tenant" if columns_.include?('tenant_')
new_columns_ << "Meter ID" if columns_.include?('meter_id_')
new_columns_ << "Meter Name" if columns_.include?('meter_id_')
new_columns_ << "van" if columns_.include?('van_')
new_columns_ << "vbn" if columns_.include?('vbn_')
new_columns_ << "vcn" if columns_.include?('vcn_')
new_columns_ << "ia" if columns_.include?('ia_')
new_columns_ << "ib" if columns_.include?('ib_')
new_columns_ << "ic" if columns_.include?('ic_')
new_columns_ << "w3pht" if columns_.include?('w3pht_')
new_columns_ << "pf3pht" if columns_.include?('pf3pht_')
new_columns_ << "f" if columns_.include?('f_')
new_columns_ << "whrec" if columns_.include?('whrec_')
new_columns_ << "whtot" if columns_.include?('whtot_')
new_columns_ << "varhrec" if columns_.include?('varhrec_')
new_columns_ << "varhtot" if columns_.include?('varhtot_')
new_columns_ << "whintvlrec" if columns_.include?('whintvlrec_')
new_columns_ << "whintvldel" if columns_.include?('whintvldel_')
new_columns_ << "w+phavg" if columns_.include?('w__phavg_')
new_columns_ << "var+3phavg" if columns_.include?('var__3phavg_')
new_columns_ << "w-3phavg" if columns_.include?('w_3phavg_')
new_columns_ << "var-3phavg" if columns_.include?('var_3phavg_')
new_columns_ << "phai" if columns_.include?('phai_')
new_columns_ << "phbi" if columns_.include?('phbi_')
new_columns_ << "phci" if columns_.include?('phci_')
new_columns_ << "w+3phmaxavgdmd" if columns_.include?('w__3phmaxavgdmd_')
new_columns_ << "var+3phmaxavgdmd" if columns_.include?('var__3phmaxavgdmd_')
new_columns_ << "w-3phmaxavgdmd" if columns_.include?('w_3phmaxavgdmd_')
new_columns_ << "var-3phmaxavgdmd" if columns_.include?('var_3phmaxavgdmd_')
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
t = 1; @meter_data.each do |m|
new_columns_data = []
if columns_.include?('date_time_')
m_date_time = m['date_time']
new_columns_data << ( m_date_time.nil? ? '--' : m_date_time)
end
if columns_.include?('building_')
m_building = m_building
new_columns_data << ( m_building.nil? ? '--' : building_names["#{m_building}"])
end
if columns_.include?('tenant_')
m_tenant = m['tenant']
new_columns_data << ( m_tenant.nil? ? '--' : tenant_names["#{m_tenant}"])
end
if columns_.include?('meter_id_')
m_meter_id = m['meter_id']
new_columns_data << ( m_meter_id.nil? ? '--' : m_meter_id)
end
if columns_.include?('meter_id_')
m_meter_id = m['meter_id']
new_columns_data << ( meter_extra.get_meter_name(m_meter_id.nil? ? '--' : m_meter_id) )
end
if columns_.include?('van_')
m_van = m.van
new_columns_data << ( m_van.nil? ? '--' : m_van )
end
if columns_.include?('vbn_')
m_vbn = m.vbn
new_columns_data << ( m_vbn.nil? ? '--' : m_vbn )
end
if columns_.include?('vcn_')
m_vcn = m.vcn
new_columns_data << ( m_vcn.nil? ? '--' : m_vcn )
end
if columns_.include?('ia_')
m_ia = m.ia
new_columns_data << ( m_ia.nil? ? '--' : m_ia )
end
if columns_.include?('ib_')
m_ib = m.ib
new_columns_data << ( m_ib.nil? ? '--' : m_ib )
end
if columns_.include?('ic_')
m_ic = m.ic
new_columns_data << ( m_ic.nil? ? '--' : m_ic )
end
if columns_.include?('w3pht_')
m_w3pht = m.w3pht
new_columns_data << ( m_w3pht.nil? ? '--' : m_w3pht )
end
if columns_.include?('pf3pht_')
m_pf3pht = m.pf3pht
new_columns_data << ( m_pf3pht.nil? ? '--' : m_pf3pht )
end
if columns_.include?('f_')
m_f = m.f
new_columns_data << ( m_f.nil? ? '--' : m_f )
end
if columns_.include?('whrec_')
m_whrec = m.whrec
new_columns_data << ( m_whrec.nil? ? '--' : m_whrec )
end
if columns_.include?('whtot_')
m_whtot = m.whtot
new_columns_data << ( m_whtot.nil? ? '--' : m_whtot )
end
if columns_.include?('varhrec_')
m_varhrec = m.varhrec
new_columns_data << ( m_varhrec.nil? ? '--' : m_varhrec )
end
if columns_.include?('varhtot_')
m_varhtot = m.varhtot
new_columns_data << ( m_varhtot.nil? ? '--' : m_varhtot )
end
if columns_.include?('whintvlrec_')
m_whintvlrec = m.whintvlrec
new_columns_data << ( m_whintvlrec.nil? ? '--' : m_whintvlrec )
end
if columns_.include?('whintvldel_')
m_whintvldel = m.whintvldel
new_columns_data << ( m_whintvldel.nil? ? '--' : m_whintvldel )
end
if columns_.include?('w__phavg_')
m_w__phavg = m.w__phavg
new_columns_data << ( m_w__phavg.nil? ? '--' : m_w__phavg )
end
if columns_.include?('var__3phavg_')
m_var__3phavg = m.var__3phavg
new_columns_data << ( m_var__3phavg.nil? ? '--' : m_var__3phavg )
end
if columns_.include?('w_3phavg_')
m_w_3phavg = m.w_3phavg
new_columns_data << ( m_w_3phavg.nil? ? '--' : m_w_3phavg )
end
if columns_.include?('var_3phavg_')
m_var_3phavg = m.var_3phavg
new_columns_data << ( m_var_3phavg.nil? ? '--' : m_var_3phavg )
end
if columns_.include?('phai_')
m_phai = m.phai
new_columns_data << ( m_phai.nil? ? '--' : m_phai )
end
if columns_.include?('phbi_')
m_phbi = m.phbi
new_columns_data << ( m_phbi.nil? ? '--' : m_phbi )
end
if columns_.include?('phci_')
m_phci = m.phci
new_columns_data << ( m_phci.nil? ? '--' : m_phci )
end
if columns_.include?('w__3phmaxavgdmd_')
m_w__3phmaxavgdmd = m.w__3phmaxavgdmd
new_columns_data << ( m_w__3phmaxavgdmd.nil? ? '--' : m_w__3phmaxavgdmd )
end
if columns_.include?('var__3phmaxavgdmd_')
m_var__3phmaxavgdmd = m.var__3phmaxavgdmd
new_columns_data << ( m_var__3phmaxavgdmd.nil? ? '--' : m_var__3phmaxavgdmd )
end
if columns_.include?('w_3phmaxavgdmd_')
m_w_3phmaxavgdmd = m.w_3phmaxavgdmd
new_columns_data << (m_w_3phmaxavgdmd.nil? ? '--' : m_w_3phmaxavgdmd )
end
if columns_.include?('var_3phmaxavgdmd_')
m_var_3phmaxavgdmd = m.var_3phmaxavgdmd
new_columns_data << ( m_var_3phmaxavgdmd.nil? ? '--' : m_var_3phmaxavgdmd )
end
if t == 1
sheet.add_row new_columns_data , :style => styles_hash[:simple_green_cell], :widths=>[20]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[20]
end
$row_num += 1
t = 0 if t == 2
t += 1
puts $row_num
m = nil
end
@meter_data = nil
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil;
end
## summary calculation ##
wb.add_worksheet(:name => "Summary") do |sheet|
$row_num = 0
sheet.add_row []
$row_num += 1
sheet.add_row ["Summary report of #{@building_f_name} #{@from_date} to #{@to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A1:Q1")
columns_ = []; @columns.each { |s| columns_ << "#{s}_".to_s }
new_columns_ = []
new_columns_ << "Meter ID"
new_columns_ << "Meter Name"
new_columns_ << "Max KW"
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
t = 0
@meter_data_max.each do |m|
new_columns_data = []
new_columns_data << m.meter_id
new_columns_data << meter_names["#{m.meter_id}"]
new_columns_data << ( m.w__3phmaxavgdmd.nil? ? '' : m.w__3phmaxavgdmd )
if t == 1
sheet.add_row new_columns_data, :style => styles_hash[:simple_green_cell], :widths=>[25]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[25]
end
$row_num += 1
t = 0 if t == 2
t += 1
m = nil;
end
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil
end
## summary calculation ##
## summary calculation ##
wb.add_worksheet(:name => "Energy consumed") do |sheet|
$row_num = 0
sheet.add_row []
$row_num += 1
sheet.add_row ["Energy consumed report of #{@building_f_name} #{@from_date} to #{@to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A2:Q2")
engery = []
@uniq_meter_id.each do |f|
start = MeterData.find_by_sql("select whtot from meter_data where `date_time_i` >= #{@from_date} AND meter_id = '#{f.meter_id}' ORDER BY date_time_i ASC limit 1")
eand = MeterData.find_by_sql("select whtot from meter_data where `date_time_i` <= #{@from_date} AND meter_id = '#{f.meter_id}' ORDER BY date_time_i DESC limit 1")
sleep 0.009
begin
engery << (eand.last.whtot.to_i - start.first.whtot.to_i)
rescue
engery << '--'
end
start = nil; eand = nil;
f = nil;
end
columns_ = []; @columns.each { |s| columns_ << "#{s}_".to_s }
new_columns_ = []
new_columns_ << "Meter ID"
new_columns_ << "Meter Name"
new_columns_ << "Subtraction result"
new_columns_ << "Aggregate result"
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
flage = 0
t = 0
@meter_sum.each do |m|
new_columns_data = []
new_columns_data << m.meter_id
new_columns_data << meter_names["#{m.meter_id}"]
new_columns_data << engery[flage]
new_columns_data << m.whintvlrec
if t == 1
sheet.add_row new_columns_data, :style => styles_hash[:simple_green_cell], :widths=>[25]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[25]
end
$row_num += 1
flage += 1
t = 0 if t == 2
t += 1
m = nil
end
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil;
end
end
$file_name = "tmp/#{@building_info} . #{@from_date} - #{@to_date} _ #{Time.new.to_i}.xlsx"
p.serialize($file_name)
p = nil; wb = nil;
@meter_data = nil; @meter_data_max = nil; @meter_sum = nil;
return $file_name
end
# total records = 5, 00, 000
def下载_数据(参数,选项={})
$file_name=“”
portfolio\u name=portfolio.get\u name
building\u names=building.get\u names
租户名称=租户。获取租户名称
meter\u names=meter.get\u meter\u names
@公文包信息、@building\u info、@tenant\u info、@meter\u id、@from\u date、@to\u date=params[:公文包名称]、params[:building\u name]、params[:tenant\u name]、params[:meter\u id]、params[:from\u date]、params[:to\u date]
@from_date=DateTime.parse(@from_date).to_i
@to_date=DateTime.parse(@to_date).to_i
@建筑物名称=建筑物名称[“{@building\u info}]
除非参数[:字段].nil?
@字段=参数[:字段]。拆分(“”)
@列=[]
@字段。每个do | f|
如果f.length>0
@“建筑数据详细信息”栏do |表|
$row_num=0
额外计量单位=新计量单位
列=[]@columns.each{| s | columns u styles_hash[:heading_cell]
$row_num+=1
sheet.add_行[]
$row_num+=1
sheet.add_行[]
$row_num+=1
表.合并单元(“A2:Q2”)
新列
new_columns\up>当ruby进程内存不足时,它会从名为heap slab的系统中访问大量内存。然后,这个大内存块会在内部划分为许多小内存块,用于保存变量和代码。当您将nil赋值给某个变量时,垃圾收集器会将这个小内存块标记为空,但整个slab永远不会被删除返回到系统,直到进程终止。我不确定这是否真的是您遇到的问题,但内存中分配的本应“短期”的对象最终意外升级为“长期”相反,由于垃圾收集器的运行频率不足以清理这些对象,导致内存膨胀:
Ruby 2.1中世代GC的作者Koichi Sasada:
“一些‘短寿命’的年轻对象将意外升级为‘老代’……如果这些‘短寿命’对象占用大量内存,我们需要释放这些对象。”
Ruby社区现在经常提到的一个问题是更改默认Ruby设置,以便告诉它更频繁地进行垃圾收集:
预期Ruby 2.1.1的内存会加倍。对此不满意吗?您有两个选择:
>p>通过减少<代码> RuyyGcHePaPoLoOdObjult.LimiTimeFase来调整它。在<代码> 1 /代码>下,您的内存消耗将与2相同。它与<代码> 2 <代码>默认> 。
选项2,等待Ruby的未来版本,这将在2.2中修复,甚至可能在2.1.2中进行更多修补。请参阅:
- 及
- 及
您是否能够用我们可以查看的小样本代码来复制问题?小样本代码也能正常工作。内存仍在使用中。请让我们看看您在样本代码中使用了什么?