■2009-02-16
* [Perl] Template::Stash::XS使用時のlength
template-toolkitでunicode文字列に対してバーチャルメソッドlengthを使うと、文字数ではなく、バイト数が返ってきて、でもsplitとかmatchとかはちゃんとunicodeに対する動作をしてます。
だいたいTemplate::VMethods::text_length自体呼ばれてないし、ってなわけで色々試してたら、Template::Stash::XSを使ったときだけ生じるので、Stash.xsをみたらscalar_dot_lengthで定義されてました。
use strict; use utf8; use Template; my $tmpl = Template->new(); my $ret = ''; my $body =<<BODY; length -- [% str.length %] split_size -- [% str.split('').size %] BODY $tmpl->process( \$body, { str => 'あいうえお' }, \$ret );
↑本当は両方5になると思うのだけど、Stash::XSを利用している場合はlengthが15。で、下記のようなパッチ(Template-2.20)をあてたのですが、これって今まで問題にならなかったのかしら? あるいは私が何か勘違いをしているのか……
--- xs/Stash.xs.bak 2009-02-16 11:20:09.000000000 +0900 +++ xs/Stash.xs 2009-02-16 11:41:15.000000000 +0900 @@ -1125,8 +1125,16 @@ /* scalar.length */ static SV *scalar_dot_length(pTHX_ SV *sv, AV *args) { STRLEN length; +#if PERL_VERSION >= 8 /* Perl 5.8 and later */ + if ( SvUTF8(sv) ) { + length = sv_len_utf8( sv ); + } + else { + length = sv_len( sv ); + } +# else SvPV(sv, length); - +# endif return sv_2mortal(newSViv((IV) length)); }
■2009-02-19
* [Perl][メモ] Template::Stash::XSとVmethodのlength続き
先日のTemplate::Stash::XS使用時のlengthで、unicodeに対応するようパッチをあててみたのですが、そもそもscalar_dot_length
使わなくてもよいんじゃないかという気がしてきて、
--- xs/Stash.xs 2009-02-19 14:33:44.000000000 +0900 +++ xs2/Stash_del_len.xs 2009-02-19 14:37:47.000000000 +0900 @@ -115,7 +115,7 @@ { "join", list_dot_join, NULL, NULL }, { "keys", NULL, hash_dot_keys, NULL }, /* { "last", list_dot_last, NULL, NULL }, */ - { "length", NULL, NULL, scalar_dot_length }, +/* { "length", NULL, NULL, scalar_dot_length }, */
で
use Benchmark qw( timethese ); use strict; use utf8; my $count = 10000; my $tmpl_pp = Template->new( { STASH => Template::Stash->new() } ); my $tmpl_xs = Template->new( { STASH => Template::Stash::XS->new() } ); my $tmpl_xs2 = Template->new( { STASH => Template::Stash::XS_del_len->new() } ); my $str_unicode = 'あいうえお' x 1000; my $body = "[% str.length %]"; timethese($count, { 'xs' => sub { my $ret = ''; $tmpl_xs->process( \$body, { str => $str_unicode }, \$ret ); }, 'xs2' => sub { my $ret = ''; $tmpl_xs2->process( \$body, { str => $str_unicode }, \$ret ); }, 'pp' => sub { my $ret = ''; $tmpl_pp->process( \$body, { str => $str_unicode }, \$ret ); }, });
(Template::Stash::XSは先日のパッチをあてたもの)
結果:
pp: 9 wallclock secs ( 8.12 usr + 0.00 sys = 8.12 CPU) @ 1231.53/s (n=10000) xs: 7 wallclock secs ( 7.32 usr + 0.02 sys = 7.34 CPU) @ 1362.40/s (n=10000) xs2: 7 wallclock secs ( 7.33 usr + 0.01 sys = 7.34 CPU) @ 1362.40/s (n=10000)
ほぼ大差ないのでscalar_dot_length
自体必要なさそうな。