merge revision(s) 6c252912af: [Backport #20145]

Memory leak when duplicating identhash

	[Bug #20145]

	Before this commit, both copy_compare_by_id and hash_copy will create a
	copy of the ST table, so the ST table created in copy_compare_by_id will
	be leaked.

	    h = { 1 => 2 }.compare_by_identity

	    10.times do
	      1_000_000.times do
	        h.select { false }
	      end

	      puts `ps -o rss= -p #{$$}`
	    end

	Before:

	    110736
	    204352
	    300272
	    395520
	    460704
	    476736
	    542000
	    604704
	    682624
	    770528

	After:

	    15504
	    16048
	    16144
	    16256
	    16320
	    16320
	    16752
	    16752
	    16752
	    16752
	---
	 hash.c                 | 10 +++++++++-
	 test/ruby/test_hash.rb | 10 ++++++++++
	 2 files changed, 19 insertions(+), 1 deletion(-)
This commit is contained in:
NARUSE, Yui 2024-02-01 09:08:06 +09:00
parent f585171a6b
commit aeffb5e21d
3 changed files with 20 additions and 2 deletions

10
hash.c
View file

@ -1557,7 +1557,15 @@ hash_copy(VALUE ret, VALUE hash)
static VALUE static VALUE
hash_dup_with_compare_by_id(VALUE hash) hash_dup_with_compare_by_id(VALUE hash)
{ {
return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash); VALUE dup = hash_alloc_flags(rb_cHash, 0, Qnil, RHASH_ST_TABLE_P(hash));
if (RHASH_ST_TABLE_P(hash)) {
RHASH_SET_ST_FLAG(dup);
}
else {
RHASH_UNSET_ST_FLAG(dup);
}
return hash_copy(dup, hash);
} }
static VALUE static VALUE

View file

@ -1458,6 +1458,16 @@ class TestHash < Test::Unit::TestCase
assert_predicate(h.dup, :compare_by_identity?, bug8703) assert_predicate(h.dup, :compare_by_identity?, bug8703)
end end
def test_compare_by_identy_memory_leak
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true)
begin;
h = { 1 => 2 }.compare_by_identity
1_000_000.times do
h.select { false }
end
end;
end
def test_same_key def test_same_key
bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each' bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each'
h = @cls[a=[], 1] h = @cls[a=[], 1]

View file

@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 0 #define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 4 #define RUBY_PATCHLEVEL 5
#include "ruby/version.h" #include "ruby/version.h"
#include "ruby/internal/abi.h" #include "ruby/internal/abi.h"