Project

General

Profile

Actions

Bug #16900

closed

Disposable call-cache introduced memory leak

Added by jeremyevans0 (Jeremy Evans) almost 4 years ago. Updated almost 4 years ago.

Status:
Closed
Target version:
-
[ruby-core:98445]

Description

b9007b6c548f91e88fd3f2ffa23de740431fa969 (Introduce disposable call-cache) introduced a memory leak for classes that include or prepend modules. Taking the example memory leak script used in the commit message for 5922c954614e5947a548780bb3b894626affe6dd:

    module M; def bar; end; end
    loop{
      Class.new do
        def foo; end
        prepend M
      end
    }

There is unbounded growth:

jeremy   56984  0.0  0.1 59540 14940 p2  S+      5:15PM    0:00.19 ruby example.rb
jeremy   56984  0.0  0.1 61852 18640 p2  S+      5:15PM    0:00.40 ruby example.rb
jeremy   56984  0.0  0.1 62700 19940 p2  S+      5:15PM    0:00.62 ruby example.rb
jeremy   56984  0.0  0.1 63696 21364 p2  S+      5:15PM    0:00.83 ruby example.rb
jeremy   56984  4.1  0.1 64632 22748 p2  S+      5:15PM    0:01.05 ruby example.rb
jeremy   56984  4.1  0.1 65664 24188 p2  S+      5:15PM    0:01.26 ruby example.rb
jeremy   56984  4.1  0.2 66632 25432 p2  S+      5:15PM    0:01.47 ruby example.rb
jeremy   56984  4.1  0.2 67484 26552 p2  S+      5:15PM    0:01.70 ruby example.rb
jeremy   56984  8.5  0.2 68456 27772 p2  S+      5:15PM    0:01.92 ruby example.rb
jeremy   56984  8.5  0.2 69536 29164 p2  S+      5:15PM    0:02.14 ruby example.rb
jeremy   56984  8.5  0.2 70424 30252 p2  S+      5:15PM    0:02.36 ruby example.rb

This issue appears to be limited to classes that include or prepend modules.

  • Same memory leak when switching from prepend to include
  • No memory leak when switching from Class.new to Module.new
  • No memory leak when removing the prepend
  • No memory leak when removing the prepend and subclassing the class.

Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago

Using the following program, I have determined that Ruby isn't leaking objects according to ObjectSpace.count_objects, so it is probably leaking some other memory.

module M; def bar; end; end
h = nil
h2 = ObjectSpace.count_objects
require 'objspace'
100.times { |i|
  10000.times {
    Class.new do
      def foo; end
      include M
    end
  }
  GC.start
  h = h2
  h2 = ObjectSpace.count_objects
  h2.each do |k,v|
    p [i, k, v, h[k]] if h[k] != v
  end
  GC.start
}

Output from the program:

[0, :TOTAL, 10601, 9786]
[0, :FREE, 4874, 1823]
[0, :T_CLASS, 440, 436]
[0, :T_STRING, 2420, 4506]
[0, :T_ARRAY, 112, 259]
[0, :T_HASH, 5, 7]
[0, :T_DATA, 111, 128]
[0, :T_IMEMO, 2565, 2554]
[0, :T_ICLASS, 27, 26]
[1, :FREE, 4866, 4874]
[1, :T_HASH, 8, 5]
[1, :T_DATA, 112, 111]
[1, :T_IMEMO, 2569, 2565]
[2, :FREE, 4865, 4866]
[2, :T_HASH, 9, 8]

This shows that after the 3rd iteration, object counts remain the same.

Actions #3

Updated by ko1 (Koichi Sasada) almost 4 years ago

  • Status changed from Open to Closed

Applied in changeset git|cbd45af2a9bec871ee023e6be57c5f32b22280fe.


fix memory leak of ccs

rb_callable_method_entry() creates ccs entry in cc_tbl, but this
code overwrite by insert newly created ccs and overwrote ccs never
freed.
[Bug #16900]

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0