From 63f524622b561ba9841cf2e0534cc722d289da3a Mon Sep 17 00:00:00 2001 From: Yorhel Date: Wed, 19 Feb 2025 12:57:33 +0100 Subject: [PATCH] bench: Re-run with more time + JSON::Tiny & XMLWriter benchmarks --- FU/Benchmarks.pod | 383 ++++++++++++++++++++++++++-------------------- FU/XMLWriter.pm | 7 + bench.PL | 99 +++++++++++- 3 files changed, 321 insertions(+), 168 deletions(-) diff --git a/FU/Benchmarks.pod b/FU/Benchmarks.pod index 651160f..2479667 100644 --- a/FU/Benchmarks.pod +++ b/FU/Benchmarks.pod @@ -30,12 +30,20 @@ The following module versions were used: =item L 0.1 +=item L 1.08 + =item L 4.16 =item L 1.06 +=item L 0.58 + =item L 4.03 +=item L 1.5 + +=item L 0.900 + =back @@ -54,215 +62,260 @@ SIMD parts are only used for parsing. API object from L documentation. Encode Canonical Decode - JSON::PP 5397/s 4973/s 1290/s - Cpanel::JSON::XS 112845/s 102903/s 101843/s - JSON::SIMD 125127/s 116569/s 117446/s - JSON::XS 128792/s 118616/s 117257/s - FU::Util 136151/s 115564/s 120184/s + JSON::PP 5312/s 5119/s 1290/s + JSON::Tiny 7757/s - 3426/s + Cpanel::JSON::XS 108187/s 101867/s 103575/s + JSON::SIMD 130137/s 118948/s 115123/s + JSON::XS 128421/s 120243/s 117940/s + FU::Util 133182/s 113275/s 118213/s Object (small) Encode Canonical Decode - JSON::PP 905/s 827/s 206/s - Cpanel::JSON::XS 42755/s 27849/s 18920/s - JSON::SIMD 48487/s 30266/s 22527/s - JSON::XS 48980/s 30558/s 24065/s - FU::Util 49346/s 26316/s 20768/s + JSON::PP 907/s 829/s 202/s + JSON::Tiny 1224/s - 499/s + Cpanel::JSON::XS 43168/s 28114/s 19229/s + JSON::SIMD 49019/s 30699/s 23267/s + JSON::XS 49814/s 31326/s 25336/s + FU::Util 44110/s 26134/s 21144/s Object (large) Encode Canonical Decode - JSON::PP 916/s 744/s 105/s - Cpanel::JSON::XS 29889/s 11629/s 16264/s - JSON::SIMD 33950/s 12050/s 22649/s - JSON::XS 34534/s 12399/s 23418/s - FU::Util 40482/s 13735/s 18161/s + JSON::PP 927/s 747/s 104/s + JSON::Tiny 1108/s - 392/s + Cpanel::JSON::XS 29672/s 12637/s 16609/s + JSON::SIMD 24418/s 12388/s 22895/s + JSON::XS 23192/s 13174/s 23553/s + FU::Util 39477/s 13567/s 17178/s Object (large, mixed unicode) Encode Canonical Decode - JSON::PP 845/s 699/s 86/s - Cpanel::JSON::XS 20563/s 1402/s 7590/s - JSON::SIMD 24996/s 1401/s 15959/s - JSON::XS 26915/s 1454/s 8848/s - FU::Util 24706/s 11403/s 9379/s + JSON::PP 817/s 679/s 86/s + JSON::Tiny 1036/s - 402/s + Cpanel::JSON::XS 20437/s 1345/s 7408/s + JSON::SIMD 25031/s 1331/s 15997/s + JSON::XS 23580/s 1375/s 8526/s + FU::Util 34435/s 11916/s 9419/s Small integers Encode Decode JSON::PP 113/s 29/s - Cpanel::JSON::XS 7235/s 6008/s - JSON::SIMD 8058/s 4335/s - JSON::XS 8036/s 5998/s - FU::Util 8701/s 5902/s + JSON::Tiny 160/s 86/s + Cpanel::JSON::XS 7137/s 6083/s + JSON::SIMD 7963/s 4361/s + JSON::XS 7915/s 6058/s + FU::Util 8565/s 5639/s Large integers Encode Decode - JSON::PP 2174/s 330/s - Cpanel::JSON::XS 31337/s 48514/s - JSON::SIMD 36876/s 52446/s - JSON::XS 36665/s 48689/s - FU::Util 122700/s 62048/s + JSON::PP 2176/s 329/s + JSON::Tiny 2999/s 1638/s + Cpanel::JSON::XS 31302/s 48892/s + JSON::SIMD 37201/s 51719/s + JSON::XS 36722/s 50110/s + FU::Util 116188/s 62110/s ASCII strings Encode Decode - JSON::PP 2922/s 341/s - Cpanel::JSON::XS 117604/s 43652/s - JSON::SIMD 136214/s 50865/s - JSON::XS 136486/s 40599/s - FU::Util 192974/s 43327/s + JSON::PP 2934/s 336/s + JSON::Tiny 4126/s 1439/s + Cpanel::JSON::XS 116744/s 43489/s + JSON::SIMD 134711/s 50429/s + JSON::XS 135419/s 43976/s + FU::Util 182026/s 44312/s Unicode strings Encode Decode - JSON::PP 5144/s 254/s - Cpanel::JSON::XS 92871/s 66032/s - JSON::SIMD 106664/s 100555/s - JSON::XS 104716/s 60538/s - FU::Util 124756/s 49825/s + JSON::PP 5113/s 253/s + JSON::Tiny 6603/s 2585/s + Cpanel::JSON::XS 91704/s 64489/s + JSON::SIMD 106928/s 102440/s + JSON::XS 105473/s 60558/s + FU::Util 217135/s 58972/s String escaping (few) Encode Decode - JSON::PP 4258/s 350/s - Cpanel::JSON::XS 133222/s 104174/s - JSON::SIMD 155205/s 148939/s - JSON::XS 123154/s 92594/s - FU::Util 202792/s 85352/s + JSON::PP 4251/s 352/s + JSON::Tiny 4704/s 1869/s + Cpanel::JSON::XS 131789/s 106306/s + JSON::SIMD 158171/s 153692/s + JSON::XS 157261/s 97676/s + FU::Util 191699/s 91177/s String escaping (many) Encode Decode - JSON::PP 2230/s 360/s - Cpanel::JSON::XS 139049/s 99260/s - JSON::SIMD 152317/s 113037/s - JSON::XS 153421/s 107918/s - FU::Util 132523/s 78199/s + JSON::PP 2224/s 366/s + JSON::Tiny 2884/s 984/s + Cpanel::JSON::XS 136583/s 100789/s + JSON::SIMD 152951/s 113242/s + JSON::XS 153471/s 106269/s + FU::Util 142604/s 97984/s + + + +=head2 XML Writing + +HTML fragment + + TUWF::XML 795/s + XML::Writer 833/s + HTML::Tiny 423/s + FU::XMLWriter 5285/s =cut # Cached data used by bench.PL. Same as the formatted tables above but easier to parse. -json/api Canonical Cpanel::JSON::XS 102903 -json/api Canonical FU::Util 115564 -json/api Canonical JSON::PP 4973 -json/api Canonical JSON::SIMD 116569 -json/api Canonical JSON::XS 118616 -json/api Decode Cpanel::JSON::XS 101843 -json/api Decode FU::Util 120184 +json/api Canonical Cpanel::JSON::XS 101867 +json/api Canonical FU::Util 113275 +json/api Canonical JSON::PP 5119 +json/api Canonical JSON::SIMD 118948 +json/api Canonical JSON::XS 120243 +json/api Decode Cpanel::JSON::XS 103575 +json/api Decode FU::Util 118213 json/api Decode JSON::PP 1290 -json/api Decode JSON::SIMD 117446 -json/api Decode JSON::XS 117257 -json/api Encode Cpanel::JSON::XS 112845 -json/api Encode FU::Util 136151 -json/api Encode JSON::PP 5397 -json/api Encode JSON::SIMD 125127 -json/api Encode JSON::XS 128792 -json/intl Decode Cpanel::JSON::XS 48514 -json/intl Decode FU::Util 62048 -json/intl Decode JSON::PP 330 -json/intl Decode JSON::SIMD 52446 -json/intl Decode JSON::XS 48689 -json/intl Encode Cpanel::JSON::XS 31337 -json/intl Encode FU::Util 122700 -json/intl Encode JSON::PP 2174 -json/intl Encode JSON::SIMD 36876 -json/intl Encode JSON::XS 36665 -json/ints Decode Cpanel::JSON::XS 6008 -json/ints Decode FU::Util 5902 +json/api Decode JSON::SIMD 115123 +json/api Decode JSON::Tiny 3426 +json/api Decode JSON::XS 117940 +json/api Encode Cpanel::JSON::XS 108187 +json/api Encode FU::Util 133182 +json/api Encode JSON::PP 5312 +json/api Encode JSON::SIMD 130137 +json/api Encode JSON::Tiny 7757 +json/api Encode JSON::XS 128421 +json/intl Decode Cpanel::JSON::XS 48892 +json/intl Decode FU::Util 62110 +json/intl Decode JSON::PP 329 +json/intl Decode JSON::SIMD 51719 +json/intl Decode JSON::Tiny 1638 +json/intl Decode JSON::XS 50110 +json/intl Encode Cpanel::JSON::XS 31302 +json/intl Encode FU::Util 116188 +json/intl Encode JSON::PP 2176 +json/intl Encode JSON::SIMD 37201 +json/intl Encode JSON::Tiny 2999 +json/intl Encode JSON::XS 36722 +json/ints Decode Cpanel::JSON::XS 6083 +json/ints Decode FU::Util 5639 json/ints Decode JSON::PP 29 -json/ints Decode JSON::SIMD 4335 -json/ints Decode JSON::XS 5998 -json/ints Encode Cpanel::JSON::XS 7235 -json/ints Encode FU::Util 8701 +json/ints Decode JSON::SIMD 4361 +json/ints Decode JSON::Tiny 86 +json/ints Decode JSON::XS 6058 +json/ints Encode Cpanel::JSON::XS 7137 +json/ints Encode FU::Util 8565 json/ints Encode JSON::PP 113 -json/ints Encode JSON::SIMD 8058 -json/ints Encode JSON::XS 8036 -json/objl Canonical Cpanel::JSON::XS 11629 -json/objl Canonical FU::Util 13735 -json/objl Canonical JSON::PP 744 -json/objl Canonical JSON::SIMD 12050 -json/objl Canonical JSON::XS 12399 -json/objl Decode Cpanel::JSON::XS 16264 -json/objl Decode FU::Util 18161 -json/objl Decode JSON::PP 105 -json/objl Decode JSON::SIMD 22649 -json/objl Decode JSON::XS 23418 -json/objl Encode Cpanel::JSON::XS 29889 -json/objl Encode FU::Util 40482 -json/objl Encode JSON::PP 916 -json/objl Encode JSON::SIMD 33950 -json/objl Encode JSON::XS 34534 -json/objs Canonical Cpanel::JSON::XS 27849 -json/objs Canonical FU::Util 26316 -json/objs Canonical JSON::PP 827 -json/objs Canonical JSON::SIMD 30266 -json/objs Canonical JSON::XS 30558 -json/objs Decode Cpanel::JSON::XS 18920 -json/objs Decode FU::Util 20768 -json/objs Decode JSON::PP 206 -json/objs Decode JSON::SIMD 22527 -json/objs Decode JSON::XS 24065 -json/objs Encode Cpanel::JSON::XS 42755 -json/objs Encode FU::Util 49346 -json/objs Encode JSON::PP 905 -json/objs Encode JSON::SIMD 48487 -json/objs Encode JSON::XS 48980 -json/obju Canonical Cpanel::JSON::XS 1402 -json/obju Canonical FU::Util 11403 -json/obju Canonical JSON::PP 699 -json/obju Canonical JSON::SIMD 1401 -json/obju Canonical JSON::XS 1454 -json/obju Decode Cpanel::JSON::XS 7590 -json/obju Decode FU::Util 9379 +json/ints Encode JSON::SIMD 7963 +json/ints Encode JSON::Tiny 160 +json/ints Encode JSON::XS 7915 +json/objl Canonical Cpanel::JSON::XS 12637 +json/objl Canonical FU::Util 13567 +json/objl Canonical JSON::PP 747 +json/objl Canonical JSON::SIMD 12388 +json/objl Canonical JSON::XS 13174 +json/objl Decode Cpanel::JSON::XS 16609 +json/objl Decode FU::Util 17178 +json/objl Decode JSON::PP 104 +json/objl Decode JSON::SIMD 22895 +json/objl Decode JSON::Tiny 392 +json/objl Decode JSON::XS 23553 +json/objl Encode Cpanel::JSON::XS 29672 +json/objl Encode FU::Util 39477 +json/objl Encode JSON::PP 927 +json/objl Encode JSON::SIMD 24418 +json/objl Encode JSON::Tiny 1108 +json/objl Encode JSON::XS 23192 +json/objs Canonical Cpanel::JSON::XS 28114 +json/objs Canonical FU::Util 26134 +json/objs Canonical JSON::PP 829 +json/objs Canonical JSON::SIMD 30699 +json/objs Canonical JSON::XS 31326 +json/objs Decode Cpanel::JSON::XS 19229 +json/objs Decode FU::Util 21144 +json/objs Decode JSON::PP 202 +json/objs Decode JSON::SIMD 23267 +json/objs Decode JSON::Tiny 499 +json/objs Decode JSON::XS 25336 +json/objs Encode Cpanel::JSON::XS 43168 +json/objs Encode FU::Util 44110 +json/objs Encode JSON::PP 907 +json/objs Encode JSON::SIMD 49019 +json/objs Encode JSON::Tiny 1224 +json/objs Encode JSON::XS 49814 +json/obju Canonical Cpanel::JSON::XS 1345 +json/obju Canonical FU::Util 11916 +json/obju Canonical JSON::PP 679 +json/obju Canonical JSON::SIMD 1331 +json/obju Canonical JSON::XS 1375 +json/obju Decode Cpanel::JSON::XS 7408 +json/obju Decode FU::Util 9419 json/obju Decode JSON::PP 86 -json/obju Decode JSON::SIMD 15959 -json/obju Decode JSON::XS 8848 -json/obju Encode Cpanel::JSON::XS 20563 -json/obju Encode FU::Util 24706 -json/obju Encode JSON::PP 845 -json/obju Encode JSON::SIMD 24996 -json/obju Encode JSON::XS 26915 -json/strel Decode Cpanel::JSON::XS 99260 -json/strel Decode FU::Util 78199 -json/strel Decode JSON::PP 360 -json/strel Decode JSON::SIMD 113037 -json/strel Decode JSON::XS 107918 -json/strel Encode Cpanel::JSON::XS 139049 -json/strel Encode FU::Util 132523 -json/strel Encode JSON::PP 2230 -json/strel Encode JSON::SIMD 152317 -json/strel Encode JSON::XS 153421 -json/stres Decode Cpanel::JSON::XS 104174 -json/stres Decode FU::Util 85352 -json/stres Decode JSON::PP 350 -json/stres Decode JSON::SIMD 148939 -json/stres Decode JSON::XS 92594 -json/stres Encode Cpanel::JSON::XS 133222 -json/stres Encode FU::Util 202792 -json/stres Encode JSON::PP 4258 -json/stres Encode JSON::SIMD 155205 -json/stres Encode JSON::XS 123154 -json/strs Decode Cpanel::JSON::XS 43652 -json/strs Decode FU::Util 43327 -json/strs Decode JSON::PP 341 -json/strs Decode JSON::SIMD 50865 -json/strs Decode JSON::XS 40599 -json/strs Encode Cpanel::JSON::XS 117604 -json/strs Encode FU::Util 192974 -json/strs Encode JSON::PP 2922 -json/strs Encode JSON::SIMD 136214 -json/strs Encode JSON::XS 136486 -json/stru Decode Cpanel::JSON::XS 66032 -json/stru Decode FU::Util 49825 -json/stru Decode JSON::PP 254 -json/stru Decode JSON::SIMD 100555 -json/stru Decode JSON::XS 60538 -json/stru Encode Cpanel::JSON::XS 92871 -json/stru Encode FU::Util 124756 -json/stru Encode JSON::PP 5144 -json/stru Encode JSON::SIMD 106664 -json/stru Encode JSON::XS 104716 +json/obju Decode JSON::SIMD 15997 +json/obju Decode JSON::Tiny 402 +json/obju Decode JSON::XS 8526 +json/obju Encode Cpanel::JSON::XS 20437 +json/obju Encode FU::Util 34435 +json/obju Encode JSON::PP 817 +json/obju Encode JSON::SIMD 25031 +json/obju Encode JSON::Tiny 1036 +json/obju Encode JSON::XS 23580 +json/strel Decode Cpanel::JSON::XS 100789 +json/strel Decode FU::Util 97984 +json/strel Decode JSON::PP 366 +json/strel Decode JSON::SIMD 113242 +json/strel Decode JSON::Tiny 984 +json/strel Decode JSON::XS 106269 +json/strel Encode Cpanel::JSON::XS 136583 +json/strel Encode FU::Util 142604 +json/strel Encode JSON::PP 2224 +json/strel Encode JSON::SIMD 152951 +json/strel Encode JSON::Tiny 2884 +json/strel Encode JSON::XS 153471 +json/stres Decode Cpanel::JSON::XS 106306 +json/stres Decode FU::Util 91177 +json/stres Decode JSON::PP 352 +json/stres Decode JSON::SIMD 153692 +json/stres Decode JSON::Tiny 1869 +json/stres Decode JSON::XS 97676 +json/stres Encode Cpanel::JSON::XS 131789 +json/stres Encode FU::Util 191699 +json/stres Encode JSON::PP 4251 +json/stres Encode JSON::SIMD 158171 +json/stres Encode JSON::Tiny 4704 +json/stres Encode JSON::XS 157261 +json/strs Decode Cpanel::JSON::XS 43489 +json/strs Decode FU::Util 44312 +json/strs Decode JSON::PP 336 +json/strs Decode JSON::SIMD 50429 +json/strs Decode JSON::Tiny 1439 +json/strs Decode JSON::XS 43976 +json/strs Encode Cpanel::JSON::XS 116744 +json/strs Encode FU::Util 182026 +json/strs Encode JSON::PP 2934 +json/strs Encode JSON::SIMD 134711 +json/strs Encode JSON::Tiny 4126 +json/strs Encode JSON::XS 135419 +json/stru Decode Cpanel::JSON::XS 64489 +json/stru Decode FU::Util 58972 +json/stru Decode JSON::PP 253 +json/stru Decode JSON::SIMD 102440 +json/stru Decode JSON::Tiny 2585 +json/stru Decode JSON::XS 60558 +json/stru Encode Cpanel::JSON::XS 91704 +json/stru Encode FU::Util 217135 +json/stru Encode JSON::PP 5113 +json/stru Encode JSON::SIMD 106928 +json/stru Encode JSON::Tiny 6603 +json/stru Encode JSON::XS 105473 +xml/a Rate FU::XMLWriter 5285 +xml/a Rate HTML::Tiny 423 +xml/a Rate TUWF::XML 795 +xml/a Rate XML::Writer 833 diff --git a/FU/XMLWriter.pm b/FU/XMLWriter.pm index a36fe84..5d27e04 100644 --- a/FU/XMLWriter.pm +++ b/FU/XMLWriter.pm @@ -126,6 +126,13 @@ your own code. For example, if you have a function to convert some data into a nicely formatted table, you could name it C or something. It's like having composable custom HTML elements, but in the backend! +Generating HTML is something that website backends tend to do a I, but +calling tons of Perl functions is generally not very fast. For that reason, +this is an XS module implemented in C. It compares favorably against a few +other XML writing modules on CPAN that I tried, but whether this approach is +faster than typical templating solutions... I've no idea. Check out +L for some benchmarks. + =head2 Top-level functions These functions all return a byte string with (UTF-8) encoded XML. diff --git a/bench.PL b/bench.PL index e057df2..d8c13d3 100755 --- a/bench.PL +++ b/bench.PL @@ -19,8 +19,12 @@ my %modules = map +($_, eval "require $_; \$${_}::VERSION"), qw/ FU Cpanel::JSON::XS JSON::PP - JSON::XS JSON::SIMD + JSON::Tiny + JSON::XS + TUWF::XML + HTML::Tiny + XML::Writer /; my %data; # "id x y" => { id x y rate exists } @@ -52,13 +56,14 @@ sub def($id, $text, $xs, @ys) { my($y, $m, @sub) = @$ya; $m ||= $y; for my($i, $x) (builtin::indexed @$xs) { + next if !$sub[$i]; my $d = "$id $x $y"; $data{$d} ||= { id => $id, x => $x, y => $y }; $d = $data{$d}; $d->{exists} = 1; delete $d->{rate} if !$oldmodules{$m} || $modules{$m} ne $oldmodules{$m}; if (!exists $d->{rate}) { - my $o = timethis -1, $sub[$i], 0, 'none'; + my $o = timethis -5, $sub[$i], 0, 'none'; $d->{rate} = sprintf '%.0f', $o->iters/$o->real; printf "%-20s%-12s%-20s%10d/s\n", $id, $x, $y, $d->{rate}; } @@ -85,6 +90,7 @@ sub defjson($name, $canon, $text, $val) { my $enc = json_format $val; def "json/$name", $text, [ 'Encode', $canon ? 'Canonical' : (), 'Decode' ], [ 'JSON::PP', undef, sub { $pp->encode($val) }, $canon ? sub { $c_pp->encode($val) } : (), sub { $pp->decode($enc) } ], + [ 'JSON::Tiny', undef, sub { JSON::Tiny::to_json($val) }, $canon ? undef : (), sub { JSON::Tiny::from_json($enc) } ], [ 'Cpanel::JSON::XS', undef, sub { $cp->encode($val) }, $canon ? sub { $c_cp->encode($val) } : (), sub { $cp->decode($enc) } ], [ 'JSON::SIMD', undef, sub { $si->encode($val) }, $canon ? sub { $c_si->encode($val) } : (), sub { $si->decode($enc) } ], [ 'JSON::XS', undef, sub { $xs->encode($val) }, $canon ? sub { $c_xs->encode($val) } : (), sub { $xs->decode($enc) } ], @@ -110,6 +116,86 @@ defjson strel => 0, 'String escaping (many)', [ map "This \" \\ needs \b\x01\x02 + +package BENCH::TUWFXML { + use TUWF::XML ':html5_', 'xml_string'; + sub f($id) { + li_ class => $id % 2 ? 'one' : undef, '+', $id % 5 > 2 ? 'two' : undef, sub { + small_ '--'x($id % 50).' ' if $id % 3; + a_ href => "/$id", + class => $id % 7 > 2 ? 'another-class' : undef, + '+' => $id % 9 < 7 ? 'and-another-one' : undef, + style => "width: ${id}px", + $id; + }; + } + sub t { xml_string sub { div_ sub { f $_ for (1..100) } } } +} + +package BENCH::XMLWriter { + my $wr; + sub f($id) { + $wr->startTag(li => class => join(' ', $id % 2 ? 'one' : (), $id % 5 > 2 ? 'two' : ())); + $wr->dataElement(small => '--'x($id % 50).' ') if $id % 3; + $wr->dataElement(a => $id, href => "/$id", class => join(' ', + $id % 7 > 2 ? 'another-class' : (), + $id % 9 < 7 ? 'and-another-one' : () + ), style => "width: ${id}px"); + $wr->endTag(); + } + sub t { + $wr = XML::Writer->new(OUTPUT => \my $str, UNSAFE => 1); + $wr->startTag('div'); + f $_ for (1..100); + $wr->endTag(); + } +} + +package BENCH::HTMLTiny { + my $h; + sub f($id) { + $h->li({ class => join(' ', $id % 2 ? 'one' : (), '+', $id % 5 > 2 ? 'two' : ()) }, [ + $id % 3 ? $h->small('--'x($id % 50).' ') : '', + $h->a({ + href => "/$id", + class => join (' ', + $id % 7 > 2 ? 'another-class' : (), + $id % 9 < 7 ? 'and-another-one' : (), + ), + style => "width: ${id}px" + }, $id), + ]); + } + sub t { + $h = HTML::Tiny->new; + $h->div(map f($_), 1..100); + } +} + +package BENCH::FUXMLWriter { + use FU::XMLWriter ':html5_', 'fragment'; + sub f($id) { + li_ class => $id % 2 ? 'one' : undef, '+', $id % 5 > 2 ? 'two' : undef, sub { + small_ '--'x($id % 50).' ' if $id % 3; + a_ href => "/$id", + class => $id % 7 > 2 ? 'another-class' : undef, + '+' => $id % 9 < 7 ? 'and-another-one' : undef, + style => "width: ${id}px", + $id; + }; + } + sub t { fragment { div_ sub { f $_ for (1..100) } } } +} + +def 'xml/a', 'HTML fragment', [ 'Rate' ], + [ 'TUWF::XML', undef, \&BENCH::TUWFXML::t ], + [ 'XML::Writer', undef, \&BENCH::XMLWriter::t ], + [ 'HTML::Tiny', undef, \&BENCH::HTMLTiny::t ], + [ 'FU::XMLWriter', 'FU', \&BENCH::FUXMLWriter::t ]; + + + + delete @data{ grep !$data{$_}{exists}, keys %data }; sub fmtbench($id, $text, $xs, $ys) { @@ -124,7 +210,10 @@ sub fmtbench($id, $text, $xs, $ys) { my ($y, $m, @ys) = @$yr; $m ||= $y; $r .= sprintf '%18s', $y; - $r .= sprintf '%10d/s', $data{"$id $xs->[$_] $y"}{rate} for (0..$#$xs); + for my $i (0..$#$xs) { + my $d = $data{"$id $xs->[$i] $y"}; + $r .= $d ? sprintf '%10d/s', $d->{rate} : sprintf '%12s', '-'; + } $r .= "\n"; } "$r\n" @@ -190,6 +279,10 @@ SIMD parts are only used for parsing. :benches ^json +=head2 XML Writing + +:benches ^xml + =cut # Cached data used by bench.PL. Same as the formatted tables above but easier to parse.