From: "NARUSE, Yui" Date: 2008-02-19T19:40:44+09:00 Subject: [ruby-dev:33860] Re: 文字列処理の高速化 ? 成瀬です。 Yukihiro Matsumoto wrote: > strlenではcoderangeが設定されないから結局UTF-8の最適化が働か > ないからのようです。対策としては > > * UTF-8最適化をENC_CODERANGE_VALIDでなくても動くようにする > (難しそう) ワードごとにまとめて数えるという手法自体は可能だと思うのですが、 validation を行いつつ数えるとなると数倍単位で遅くなってしまうでしょうね。 ワード単位で validation ってのも考えてはいるのですが、早くとも10倍未満な うえに 1 度しか行わないのでシステムに対するインパクトが低く、一方でかな り複雑になりそうなので、素直にバイト単位で読んだ方がよさそうです。 > * strlenでcoderange_scan()相当を同時に行う こちらに加えて、[ruby-dev:33851] の文字列リテラルや IO coderange_scan 自体の最適化がありえるかなと思っています。 > パッチです。だれかがクリーンアップしてくれるとうれしい。 とりあえず、 + if (*cr != ENC_CODERANGE_BROKEN) + *cr = ENC_CODERANGE_VALID; という分岐をなくしてみました。 --- string.c (revision 15548) +++ string.c (working copy) @@ -619,10 +619,63 @@ rb_enc_strlen(const char *p, const char return c; } +long +rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr) +{ + long c; + const char *q; + int ret; + + *cr = 0; + if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { + return (e - p) / rb_enc_mbminlen(enc); + } + else if (rb_enc_asciicompat(enc)) { + c = 0; + while (p < e) { + if (ISASCII(*p)) { + q = search_nonascii(p, e); + if (!q) { + return c + (e - p); + } + c += q - p; + p = q; + } + ret = rb_enc_precise_mbclen(p, e, enc); + if (MBCLEN_CHARFOUND_P(ret)) { + *cr |= ENC_CODERANGE_VALID; + p += MBCLEN_CHARFOUND_LEN(ret); + } + else { + *cr = ENC_CODERANGE_BROKEN; + p++; + } + c++; + } + if (!*cr) *cr = ENC_CODERANGE_7BIT; + return c; + } + + for (c=0; p DBDB A476 FDBD 9450 02CD 0EFC BCE3 C388 472E C1EA