Project

General

Profile

Actions

Bug #15088

closed

Leaky behaviour when GC disabled

Added by william101 (William Tabi) over 5 years ago. Updated over 5 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.4.4p296 (2018-03-28 revision 63013) [x86_64-darwin17]
[ruby-core:88892]

Description

Hello

I've observed some leaky behaviour when creating dynamic Symbols ("string".to_sym) when GC is disabled. Creating a dynamic symbol after running GC.disable creates an extra string allocation that isn't garbage collected when GC is enabled later on in the code.

Based on https://bugs.ruby-lang.org/issues/9634 and https://bugs.ruby-lang.org/issues/7791, I would have expected all the memory allocated by #to_sym to be GC'ed

I can reproduce this using

# frozen_string_literal: true

require 'objspace'

GC.start

puts"Before - All: #{ObjectSpace.each_object.count}"
puts"Before - Symbols: #{Symbol.all_symbols.size}"

GC.start
GC.disable

100_000.times do |i|
  "to_sym_#{i}".to_sym
end

GC.enable
GC.start

puts"After - All: #{ObjectSpace.each_object.count}"
puts"After - Symbols: #{Symbol.all_symbols.size}"

This is the output:

with latest master v2.6.0-dev

$ RBENV_VERSION=2.6.0-dev ruby -v /tmp/test.rb
ruby 2.6.0dev (2018-09-07 trunk 64657) [x86_64-darwin17]
Before - All: 10740
Before - Symbols: 3206
After - All: 110739
After - Symbols: 3206

with ruby v2.2.2

$ RBENV_VERSION=2.2.2 ruby -v /tmp/test.rb
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin17]
Before - All: 6342
Before - Symbols: 2536
After - All: 106344
After - Symbols: 2536

Would anyone know if this is expected behaviour or a bug?

Updated by normalperson (Eric Wong) over 5 years ago

wrote:

https://bugs.ruby-lang.org/issues/15088

100_000.times do |i|
"to_sym_#{i}".to_sym
end

GC.enable
GC.start

You need at least another call to GC.start, here.

I think it is because global_symbols.dsymbol_fstr_hash (in
symbol.c) is a GC root, so rb_gc_free_dsymbol needs to be called
to remove the string from dsymbol_fstr_hash by the first
GC.start before the underlying fstring object in
vm->frozen_strings can be freed by the second GC.start call.

Updated by ko1 (Koichi Sasada) over 5 years ago

  • Status changed from Open to Rejected

Thank you Eric.

This is my 2nd experiment:

...
# adding the following code to original trial code.
GC.start

puts"After2 - All: #{ObjectSpace.each_object.count}"
puts"After2 - Symbols: #{Symbol.all_symbols.size}"

And I got:

ruby 2.6.0dev (2018-08-13 trunk 64328) [x64-mswin64_140]
Before - All: 10727
Before - Symbols: 3170
After - All: 110729
After - Symbols: 3170
After2 - All: 10731
After2 - Symbols: 3170

Updated by william101 (William Tabi) over 5 years ago

Thank you @normalperson (Eric Wong) & @ko1 (Koichi Sasada) for taking a look and for the explanation here 😀

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0