Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JRuby - How to start the garbage collector?

I fired up my JRuby irb console and typed:

irb(main):037:0* GC.enable
(irb):37 warning: GC.enable does nothing on JRuby
=> true
irb(main):038:0> GC.start
=> nil
irb(main):039:0> 

How can I manually enable or start the JVM garbage during a program?

I ask because I have a program which is needs to generate about 500 MBytes of test data and save it in MySQL. The program uses about 5 levels of nested loops, and it crashes with a JVM memory heap exception after generating about 100 MBytes of test data because there is no more heap memory. I would like to give let the garbage collector run after every run of the outer loop so that all the orphaned objects created in the inner loops can be cleaned up .

like image 520
Jay Godse Avatar asked May 24 '12 14:05

Jay Godse


People also ask

When you request garbage collector to run it will start to run immediately?

It is not possible to run garbage collection immediately as we are programming in managed environment and only CLR decides when to run garbage collection.

How does the garbage collector works?

The garbage collector considers unreachable objects garbage and releases the memory allocated for them. During a collection, the garbage collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects.

How does GC work in Ruby?

The Ruby Garbage Collector module is an interface to Ruby's mark and sweep garbage collection mechanism. While it runs automatically in the background when needed, the GC module lets you call the GC manually whenever required and gain insights into how garbage collection cycles are running.


1 Answers

The exact answer to your question would be:

require 'java'

java_import 'java.lang.System'

# ...

System.gc()

though, bearing in mind even though the JVM usually does run the GC, it may or may not do it – very dependent on the JVM implementation. It can also be quite a hit on performance.

A better answer is obviously to ensure that at the end of the nested loop, no reference is held on the test data you are generating, so that they can indeed be reclaimed by the GC later on. Example:

class Foo; end

sleep(5)

ary = []
100_000.times { 100_000.times{  ary << Foo.new }; puts 'Done'; ary = [] }

If you run this with jruby -J-verbose:gc foo.rb, you should see the GC regularly claiming the objects; this is also quite clear using JVisualVM (the sleep in the example is to give some time to connect to the Jruby process in JVisualVM).

Lastly you can increase heap memory by adding the following flag: -J-Xmx256m; see the JRuby wiki for more details.

Edit: Coincidentally, here is a mindmap on GC tuning recently presented by Mario Camou at Madrid DevOps re-posted by Nick Sieger.

like image 63
Sébastien Le Callonnec Avatar answered Nov 14 '22 09:11

Sébastien Le Callonnec