在 ruby 中运行手动 GC 是个好习惯吗

问题描述 投票:0回答:3

我在 Google 上读到很多关于 ruby 不会将内存释放给操作系统的文章,我也理解这一点,因为从操作系统分配内存是一个昂贵的公平。

这让我问这个问题

如果开发人员希望 Ruby 将内存从 Ruby 释放回操作系统,他们会如何做。

- 我猜答案是在 Ruby 中手动触发

GC

但是建议在生产应用程序上执行(运行手动 GC)吗?

我正在考虑在 Celluloid 中创建一个单独的线程(或 Actor),以每 2 小时启动一次 GC。

任何人都可以建议吗?上述解决方案是否适合生产?

注意:我想我也知道GC.start(意味着停止Ruby中的整个世界)

注:Ruby 版本 2.2.2 MRI Centos 4G RAM,4 核。

这就是问题的原因http://pastebin.com/rYdYwxLJ

ruby garbage-collection
3个回答
8
投票

我在 Google 上读到很多关于 ruby 不会将内存释放给操作系统的文章,我也理解这一点,因为从操作系统分配内存是一个昂贵的公平。

这根本不是真的。 Ruby 语言根本没有提及将内存释放回操作系统。事实上,Ruby 语言并没有提及任何有关内存的内容。

Ruby 有很多不同的实现,有很多不同的内存分配器和很多不同的垃圾收集器。有些将内存释放回操作系统,有些则不然,有些运行在托管运行时之上,甚至根本不管理内存。

例如,在 J9 上运行的 JRuby 会将内存释放回操作系统。使用 G1 GC、ParallelScavenge GC 或 ParallelOld GC 在 HotSpot 上运行的 JRuby 会将内存释放回操作系统。

如果开发人员希望 Ruby 将内存从 Ruby 释放回操作系统,他们会如何做。

你不知道。该实现要么将内存释放回操作系统,在这种情况下您不需要执行任何操作,要么它不会将内存释放回操作系统,在这种情况下您无法执行任何操作。

- 我猜答案是在 Ruby 中手动触发

GC

如果实现不将内存释放回操作系统,则它不会将内存释放回操作系统。期间。

如果实现确实将内存释放回操作系统,那么无论您是否手动触发GC,它都会这样做。

顺便说一下:Ruby 中无法手动触发 GC。您可以建议 GC(使用

GC::start
),但不能触发它。

但是建议在生产应用程序上执行(运行手动 GC)吗?

几乎从来没有。 GC 比您更清楚现在运行还是稍后运行是否有意义。

注意:我想我也知道GC.start(意味着停止Ruby中的整个世界)

不,

GC::start
只是建议进行GC。它“不会”强制执行 GC。另外,GC 并不意味着停止世界。例如。当使用 Metronome GC 在 J9 JVM 上运行 JRuby 或使用 Pauseless GC 在 Azul Zing JVM 上运行 JRuby 时,将永远停止世界。

注意:Ruby 版本 2.2.2

这不是有趣的地方。有趣的问题是您正在使用哪种实现、哪个垃圾收集器以及哪个操作系统。 (当然还有所有这些的版本和配置设置。)


4
投票
不会释放到操作系统

。时期。 您无法强制 Ruby 将 Ruby 堆释放回操作系统(除了整个应用程序的冷重启。)

可能会释放回操作系统的内容由 Ruby 内部释放,

手动调用 GC 是一种不好的做法

,在 99% 的情况下会减慢应用程序的速度,在其余 1% 的情况下这会完全没有效果


0
投票
GC.start

。据我了解,它们分配的内存不受 Ruby 监控,因此不会触发 GC。

我可以想象这样的用例:长时间运行的进程分配一些内存,但随后不会触发 GC 条件,从而导致内存被保留。在这种情况下,我打电话给 

GC.start

确实有意义。

GC.start

用例示例,使用

gdk_pixbuf2
gem 和高分辨率图像:
[1] pry(main)> 10.times do
[1] pry(main)*   GdkPixbuf::Pixbuf.new(file: 'tmp/high-res-small-size-16000x11000px.jpg')
[1] pry(main)*   puts "#{`ps -p #{Process.pid} -o 'rss='`.to_i / 1000}MB"
[1] pry(main)* end
897MB
1413MB
1929MB
2444MB
2960MB
3476MB
3991MB
4507MB
Killed

[1] pry(main)> 10.times do
[1] pry(main)*   GdkPixbuf::Pixbuf.new(file: 'tmp/high-res-small-size-16000x11000px.jpg')
[1] pry(main)*   GC.start
[1] pry(main)*   puts "#{`ps -p #{Process.pid} -o 'rss='`.to_i / 1000}MB"
[1] pry(main)* end

897MB
897MB
897MB
897MB
897MB
897MB
897MB
897MB
897MB
897MB
	
© www.soinside.com 2019 - 2024. All rights reserved.