From: Yukihiro Matsumoto Date: 2008-02-19T09:20:45+09:00 Subject: [ruby-dev:33849] Re: 文字列処理の高速化 ? まつもと ゆきひろです In message "Re: [ruby-dev:33838] 文字列処理の高速化 ?" on Mon, 18 Feb 2008 16:10:34 +0900, Martin Duerst writes: |ただの一例ですが、先週の金曜日に松本さんに見せたときに |50秒ぐらいかかったプログラムはその後の commit でおそくなり、 |65秒ぐらいかかっています。プログラムは以下の通り |(以前 Wolfgang Na'dasi-Donner が ruby-core に出した |ものがベースになっています。) |特に金曜日の夕方あたり文字列処理や UTF-8 の処理を早くする |commit が色々ありましたので、なぜで遅くなるのかをちょっと |疑問に思っています。 strlenではcoderangeが設定されないから結局UTF-8の最適化が働か ないからのようです。対策としては * UTF-8最適化をENC_CODERANGE_VALIDでなくても動くようにする (難しそう) * strlenでcoderange_scan()相当を同時に行う のいずれかが考えられます。とりあえず、後者の対策を実装してみ たところ、Martinさんの例では23.95sが2.89sになりました。 パッチです。だれかがクリーンアップしてくれるとうれしい。 diff --git a/string.c b/string.c --- a/string.c +++ b/string.c @@ -619,10 +619,64 @@ rb_enc_strlen(const char *p, const char *e, rb_encoding *enc) 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)) { + *cr = ENC_CODERANGE_7BIT; + 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)) { + if (*cr != ENC_CODERANGE_BROKEN) + *cr = ENC_CODERANGE_VALID; + p += MBCLEN_CHARFOUND_LEN(ret); + } + else { + *cr = ENC_CODERANGE_BROKEN; + p++; + } + c++; + } + return c; + } + + for (c=0; p