gpt4 book ai didi

ruby-on-rails - 使数组无效后不会释放 Ruby 内存

转载 作者:数据小太阳 更新时间:2023-10-29 08:03:20 26 4
gpt4 key购买 nike

我认为用下面的例子更容易表达我的问题:

我使用的是纯 Ruby 2.2.2,但在 Rails 4.2.2 上也是如此。

require 'bigdecimal'
x = 20000000

第一种情况:

big_number = BigDecimal.new(500)
x.times {|i| @array << big_number }

第二种情况:

(x/20).times {|i| @array << BigDecimal.new(500) }

在取消对象@array 和垃圾收集器执行后,在第一种情况下,内存使用返回到初始状态。在第二种情况下,内存永远不会被释放。

较大的内存使用量(20 倍)可能是因为第一种情况使用引用,第二种情况使用新对象,但为什么第二种情况未释放内存?

完整的示例代码:

def show_memory
size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1]
puts "#{size}"
end

# Starts with the same 14 Mb on IRB
require 'bigdecimal'
x = 20000000

puts "With variable"
5.times {
array = []
hash = BigDecimal.new(500)
x.times {|i| array << hash }
show_memory
array = nil
GC.start
show_memory
}

puts "\nWithout variable"
y = x/20
5.times {
array = []
y.times {|i| array << BigDecimal.new(500) }
show_memory
array = nil
GC.start
show_memory
}

输出:

With variable
165448
9460
165564
9464
165564
9464
165564
9464
165564
9464

Without variable
158068
150388
167016
167016
167016
167016
167016
167016
167016
167016

附言编辑问题以使用 Yacine 的评论。

最佳答案

我试过你的代码,稍作修改以具有实时内存:

def show_memory
size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1]
puts "#{size}"
end

# Starts with the same 14 Mb on IRB
require 'bigdecimal'
x = 2000000
@array = []

show_memory

x.times {|i| @array << BigDecimal.new(500) }

show_memory

# The used memory is now about 760Mb
@array = nil
GC.start
show_memory

在第一个代码中,我得到:

7552309572285792

在我得到的第二个代码中:

7232768964647928

所以他们两个都没有释放内存。我猜 Ruby VM 像 Java 一样处理他自己的内存管理,只是为你的应用程序扩大堆然后以后不会禁止它。

可以肯定的是,我再次更新了代码,这样写:

def show_memory
size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1]
puts "#{size}"
end

# Starts with the same 14 Mb on IRB
require 'bigdecimal'
x = 2000000

50.times {
@array = []
x.times {|i| @array << BigDecimal.new(500) }
show_memory
@array = nil
GC.start
show_memory
}

内存增加到 ~600Mb,然后永远保持在这个水平,证明没有内存泄漏,而是一些核心内存管理:

内存值@array loaded/@array nil:

312508
278500
348688
331172
361208
359160
391664
386544
415280
414264
444316
441244
458152
448744
466632
464584
480320
479192
498196
495132
514208
514208
530620
529596
553976
551284
567784
565736
582284
579212
595224
589080
616952
607820
613300
594588
602404
586776
602612
601588
618032
602404
618440
594628
609512
593884
609724
590000
606972
591352
607236
590584
606276
590648
606284
588608
604272
587620
607452
591824
608428
590752
606852
588152
603820
583072
604672
598596
599892
584264
591904
575252
592588
592588
608808
593188
609244
592592
609572
593236
615500
598848
615452
597776
614124
587240
608284
583448
600004
584376
600052
581352
598748
583128
599984
584356
...

如您所见,它增长并...保持在 600Mb。

如果您计划有很多 ruby​​ 进程但没有那么多 RAM 来处理它们,这仍然是个问题。也许这个“ceil”可以配置,但我没有想法。

希望对您有所帮助!

关于ruby-on-rails - 使数组无效后不会释放 Ruby 内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33550382/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com