How slow "HTML escape" is?

そういえばXslateのHTMLエスケープってどのくらい遅いのだろか、と思い、変数展開のベンチマークに「HTMLエスケープなし」を加えて測ってみたところ、驚くべき結果になった。
以下の"xslate"が<: $value :>で、"xslate/raw"が<: $value | raw :>の速度の比較である。

benchmark/interolate.pl

$ perl benchmark/interpolate.pl
Perl/5.10.1 i686-linux
Text::Xslate/0.1053
Text::MicroTemplate/0.13
1..4
ok 1 - xslate/raw (w/o escaping)
ok 2 - Text::MicroTemplate
ok 3 - s///g
ok 4 - sprintf
              Rate      s///g        TMT xslate/raw     xslate    sprintf
s///g       6400/s         --        -6%       -58%       -85%       -85%
TMT         6826/s         7%         --       -55%       -84%       -85%
xslate/raw 15175/s       137%       122%         --       -64%       -66%
xslate     41918/s       555%       514%       176%         --        -5%
sprintf    44111/s       589%       546%       191%         5%         --

なんと、rawフィルタをつけると圧倒的に遅くなってしまう!rawフィルタは最適化によって取り除かれるので、その分のオーバーヘッドはないはずだ。これは、最適化されたHTMLエスケープルーチンよりPerl_sv_catsv()の方が遅いのだろう。
これはいくらなんでもあまりにひどいので、raw文字列の出力を最適化したところ、以下のようになった。

              Rate      s///g        TMT    sprintf     xslate xslate/raw
s///g       6400/s         --        -6%       -88%       -90%       -91%
TMT         6826/s         7%         --       -87%       -90%       -90%
sprintf    52609/s       722%       671%         --       -20%       -25%
xslate     66166/s       934%       869%        26%         --        -5%
xslate/raw 69818/s       991%       923%        33%         6%         --

目論見通り、rawフィルタをかけた方がわずかに高速になった。しかし、その差は僅かである*1

脱線したがとにかく、十分に最適化すれば、HTMLエスケープ処理によるオーバーヘッドは無視していいくらい小さくなるようだ。無駄なオーバーヘッドがかかることを心配してrawフィルタやescape => "none"オプションを使う必要はまったくない。

*1:エスケープ処理をするほうも速くなっているのは、raw文字列の出力も含んでいるからである。