From: Tanaka Akira Date: 2003-07-22T19:16:40+09:00 Subject: [ruby-dev:20785] iconv fail time iconv で変換に失敗した時に入力のサイズに比例した時間がかかることがある ことに気がつきました。 このため、失敗したところをとばして続きをやるというようなことをすると、 入力全体に対して O(n**2) な時間がかかることがあります。 問題は例外オブジェクトを生成する時に残りの入力を inspect するといとこ ろが主因のようなので、とりあえず次のように変えたいんですが、どうでしょ う? あと、ついでに、rb_str_derive も変えてあります。これは failed の中身を 共有して高速化するのが狙いです。まぁ、試してみたら少ししか効きませんで したが。 Index: ext/iconv/iconv.c =================================================================== RCS file: /src/ruby/ext/iconv/iconv.c,v retrieving revision 1.7 diff -u -p -r1.7 iconv.c --- ext/iconv/iconv.c 18 Jul 2003 19:51:42 -0000 1.7 +++ ext/iconv/iconv.c 22 Jul 2003 09:30:22 -0000 @@ -230,8 +230,15 @@ iconv_failure_initialize struct iconv_env_t *env; #endif /* HAVE_PROTOTYPES */ { - if (NIL_P(rb_attr_get(error, rb_mesg))) - rb_ivar_set(error, rb_mesg, rb_inspect(failed)); + if (NIL_P(rb_attr_get(error, rb_mesg))) { + if (TYPE(failed) != T_STRING || RSTRING(failed)->len < 16) + rb_ivar_set(error, rb_mesg, rb_inspect(failed)); + else { + VALUE mesg = rb_inspect(rb_str_substr(failed, 0, 16)); + rb_str_cat2(mesg, "..."); + rb_ivar_set(error, rb_mesg, mesg); + } + } if (env) { success = rb_funcall3(env->ret, rb_inserter, 1, &success); if (env->argc > 0) { @@ -261,7 +268,10 @@ rb_str_derive return rb_str_new(ptr, len); if (RSTRING(str)->ptr == ptr && RSTRING(str)->len == len) return str; - ret = rb_str_new(ptr, len); + if (RSTRING(str)->ptr + RSTRING(str)->len == ptr + len) + ret = rb_str_substr(str, ptr - RSTRING(str)->ptr, len); + else + ret = rb_str_new(ptr, len); OBJ_INFECT(ret, str); return ret; } -- [田中 哲][たなか あきら][Tanaka Akira]