Issue #4962 has been reported by Yusuke Endoh.

----------------------------------------
Bug #4962: come back gem_prelude!
http://redmine.ruby-lang.org/issues/4962

Author: Yusuke Endoh
Status: Open
Priority: Normal
Assignee: Eric Hodel
Category: lib
Target version: 1.9.3
ruby -v: ruby 1.9.3dev (2011-07-01 trunk 32356) [i686-linux]


Hello, rubygems developers

Kosaki-san noticed that 1.9.3 is slower than 1.9.2 on many benchmarks.
http://www.atdot.net/sp/view/5qunnl

I investigated and found that the cause is the lack of gem_prelude.rb.

Loading rubygems seems to create many objects and keep the references
to them.  See below:


$ ruby -ve 'GC.start; p ObjectSpace.count_objects[:TOTAL]'
ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
9821

$ ./ruby -ve 'GC.start; p ObjectSpace.count_objects[:TOTAL]'
ruby 1.9.3dev (2011-07-01 trunk 32356) [i686-linux]
19638

$ ./ruby --disable-gems -ve 'GC.start; p ObjectSpace.count_objects[:TOTAL]'
ruby 1.9.3dev (2011-07-01 trunk 32356) [i686-linux]
9821


The number of live objects is proportional to the cost of GC mark phase.
You can actually confirm the performance degradation with the following
benchmark script:

  require 'tempfile'
  max = 200_000
  str = "Hello world!  " * 1000
  f = Tempfile.new('yarv-benchmark')
  f.write str
  GC::Profiler.enable
  max.times{
    f.seek 0
    f.read
  }
  p GC::Profiler.total_time


$ time ruby -v bm_io_file_read.rb
ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
0.7280460000000308

real    0m3.965s
user    0m2.940s
sys     0m1.024s

$ time ./ruby -v bm_io_file_read.rb
ruby 1.9.3dev (2011-07-01 trunk 32356) [i686-linux]
1.396088000000029

real    0m4.786s
user    0m3.716s
sys     0m1.060s

$ time ./ruby --disable-gems -v bm_io_file_read.rb
ruby 1.9.3dev (2011-07-01 trunk 32356) [i686-linux]
0.7640390000000309

real    0m4.079s
user    0m2.872s
sys     0m1.192s


The performance degradation can be seen by not only such micro benckmarks,
but also my puzzle solvers :-(


There are some approaches to address the problem:

  1. to introduce a generational GC; this is impossible until 2.0 because
     it requires modifications to all extension libraries.

  2. to diet rubygems; do not create any string, array, hash, and any
     object as much as possible, and do not keep the references to them.

  3. to restore gem_prelude.rb to delay loading rubygems.

I guess that 3 is a reasonable choice for 1.9.3.  But I'm fine with any
solution to fix rubygems if 1.9.3 becomes as fast as 1.9.2 on the
benchmarks.

-- 
Yusuke Endoh <mame / tsg.ne.jp>


-- 
http://redmine.ruby-lang.org