From: wanabe Date: 2009-02-05T01:43:08+09:00 Subject: [ruby-dev:37908] Re: 配列の重複検出用Hashの使いまわし ワナベです。 2009/02/04 14:45 wanabe : > 2009/02/04 13:34 Tanaka Akira : >> In article <8964790c0902032007n708f1587je29b391281bf5932@mail.gmail.com>, >> wanabe writes: >> >>> ruby-1.9では配列内の重複要素の検出のために >>> 内部でHashオブジェクトが生成されますが、 >>> これをスレッドローカルに保存して使いまわすことで >>> オブジェクト生成とGCの回数を減らすパッチを書きました。 >> >> Hash の操作をすると hash や eql? メソッドを呼びますが、その >> 中でまた重複要素の検出が必要になることはないのでしょうか。 > > ご指摘ありがとうございます。 > 確かにそういったケースでは問題がありました。失礼しました。 > > $ ./ruby -e 'class Foo;def hash;[]|[];return super;end;end;a=[Foo.new, > Foo.new];p a,a|[]' > [#, #] > [] 使用済みHashオブジェクトを配列に保存して そこから使いまわすように書き直しました。 $ ./ruby -e 'class Foo;def hash;[]|[];return super;end;end;a=[Foo.new, Foo.new];p a,a|[]' [#, #] [#, #] $ ./ruby -Ilib ../bm_array_overlap.rb user system total real & 3.547000 0.032000 3.579000 ( 3.671875) | 5.422000 0.109000 5.531000 ( 6.765625) - 3.468000 0.047000 3.515000 ( 4.312500) --- with thread --- & 18.157000 23.281000 41.438000 ( 52.609375) | 20.546000 22.984000 43.530000 ( 55.109375) - 21.016000 23.969000 44.985000 ( 57.359375) --- GC.disable --- & 3.765000 0.047000 3.812000 ( 4.093750) | 5.641000 0.078000 5.719000 ( 5.828125) - 3.531000 0.078000 3.609000 ( 3.687500) Index: array.c =================================================================== --- array.c (revision 22029) +++ array.c (working copy) @@ -2866,9 +2866,24 @@ static VALUE ary_make_hash(VALUE ary1, VALUE ary2) { - VALUE hash = rb_hash_new(); + VALUE hash; long i; + hash = rb_thread_local_aref(rb_thread_current(), + rb_intern("ary_overlap_check_hash_set")); + if (hash == Qnil) { + rb_thread_local_aset(rb_thread_current(), + rb_intern("ary_overlap_check_hash_set"), + rb_ary_new()); + } else { + hash = rb_ary_pop(hash); + if (hash != Qnil) { + rb_funcall(hash, rb_intern("clear"), 0); + } + } + if (hash == Qnil) { + hash = rb_hash_new(); + } for (i=0; i an_array @@ -2906,6 +2929,7 @@ if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue; rb_ary_push(ary3, rb_ary_elt(ary1, i)); } + ary_recycle_hash(hash); return ary3; } @@ -2940,6 +2964,7 @@ rb_ary_push(ary3, v); } } + ary_recycle_hash(hash); return ary3; } @@ -2978,6 +3003,7 @@ rb_ary_push(ary3, v); } } + ary_recycle_hash(hash); return ary3; } @@ -3013,6 +3039,7 @@ } } ARY_SET_LEN(ary, j); + ary_recycle_hash(hash); return ary; } -- ワナベ