Issue #10537 has been updated by Eric Wong. Thanks, the following patch should fix it. Your test runs much in less than 20s and uses 10M on my older x86-64 machine. It took over 2 minutes before. (lightly tested, and I'm unfamiliar with the weakmap code): --- a/gc.c +++ b/gc.c @@ -2360,6 +2360,21 @@ define_final0(VALUE obj, VALUE block) if (st_lookup(finalizer_table, obj, &data)) { table = (VALUE)data; + + /* avoid duplicate block, table is usually small */ + { + const VALUE *ptr = RARRAY_CONST_PTR(table); + long len = RARRAY_LEN(table); + long i; + + for (i = 0; i < len; i++, ptr++) { + if (rb_funcall(*ptr, idEq, 1, block)) { + rb_gc_force_recycle(block); + return *ptr; + } + } + } + rb_ary_push(table, block); } else { ---------------------------------------- Bug #10537: Repeated creation and garbage collection of WeakRef instances against a single object leaks memory https://bugs.ruby-lang.org/issues/10537#change-50062 * Author: Alex Boyd * Status: Open * Priority: Normal * Assignee: * Category: lib * Target version: * ruby -v: ruby 2.2.0dev (2014-11-24 trunk 48552) [x86_64-darwin14] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN ---------------------------------------- ~~~ require 'weakref' a = Object.new 1_000_000.times do WeakRef.new a end GC.start ~~~ The above results in Ruby consuming ~150 MB of RAM, all of which can only be freed by dropping `a`. This should not be the case - an object being weakly referenced should not itself hold a reference to the WeakRef (or any associated data) pointing at it. -- https://bugs.ruby-lang.org/