From: Yusuke ENDOH Date: 2008-03-06T22:40:07+09:00 Subject: [ruby-dev:34003] Re: [ ruby-Bugs-17454 ] irb crash while iterating over all objects 遠藤と申します。 08/02/25 に U.Nakamura さんは書きました: > In message "[ruby-dev:33931] Re: [ ruby-Bugs-17454 ] irb crash while iterating over all objects" > on Feb.25,2008 15:08:35, wrote: > | |このBignumの正体はProcess::RLIM_INFINITYなどであるということ > | |で、別に怪しいものではないことは判明したのですが、同じコード > | |をtrunkで実行すると、さらに大量の巨大なBignumが多数出現します。 > | | > | |その正体は、bignum.c内のpower_cache_init()で生成しているもの > | |なのですが、これってBignum#to_s相当の処理をしない限り使われな > | |いものなので、ruby起動時に絶対生成するんじゃなくて、初めて相 > | |当の処理が行われたときに生成するようにしたほうがいいんじゃな > | |いでしょうか? > | > | そういうパッチは歓迎します。 > > 入れました(r15598)。 > 条件判定の回数が少なくなるように、なるべく処理の上の方に入れ > たつもりです。 せっかくなので、base ごとに初期化を遅延するようにしてみました。 2, 8, 10, 16 以外の base はめったに使わないと思いますので。 # puts 809608041709942.to_s(33) Index: bignum.c =================================================================== --- bignum.c (revision 15720) +++ bignum.c (working copy) @@ -737,17 +737,13 @@ #define MAX_BIG2STR_TABLE_ENTRIES 64 static VALUE big2str_power_cache[35][MAX_BIG2STR_TABLE_ENTRIES]; -static int power_cache_initialized = 0; static void power_cache_init(void) { int i, j; for (i = 0; i < 35; ++i) { - big2str_power_cache[i][0] = - rb_big_pow(rb_int2big(i+2), INT2FIX(KARATSUBA_DIGITS)); - rb_global_variable(&big2str_power_cache[i][0]); - for (j = 1; j < MAX_BIG2STR_TABLE_ENTRIES; ++j) { + for (j = 0; j < MAX_BIG2STR_TABLE_ENTRIES; ++j) { big2str_power_cache[i][j] = Qnil; } } @@ -758,7 +754,8 @@ { if (NIL_P(big2str_power_cache[base - 2][i])) { big2str_power_cache[base - 2][i] = - bigsqr(power_cache_get_power0(base, i - 1)); + i == 0 ? rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS)) + : bigsqr(power_cache_get_power0(base, i - 1)); rb_global_variable(&big2str_power_cache[base - 2][i]); } return big2str_power_cache[base - 2][i]; @@ -905,10 +902,6 @@ return big2str_orig(x, base, ptr, len, hbase, trim); } - if (!power_cache_initialized) { - power_cache_init(); - power_cache_initialized = 1; - } b = power_cache_get_power(base, n1, &m1); bigdivmod(x, b, &q, &r); lh = big2str_karatsuba(q, base, ptr, (len - m1)/2, @@ -2616,4 +2609,6 @@ rb_define_method(rb_cBignum, "size", rb_big_size, 0); rb_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0); rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0); + + power_cache_init(); } -- Yusuke ENDOH