diff --git a/FU/Benchmarks.pod b/FU/Benchmarks.pod index 2479667..37415ff 100644 --- a/FU/Benchmarks.pod +++ b/FU/Benchmarks.pod @@ -26,9 +26,11 @@ The following module versions were used: =over -=item L 4.38 +=item L 4.39 -=item L 0.1 +=item L 3.18.0 + +=item L 0.5 =item L 1.08 @@ -40,6 +42,8 @@ The following module versions were used: =item L 4.03 +=item L 0.15 + =item L 1.5 =item L 0.900 @@ -56,266 +60,294 @@ These benchmarks run on large-ish arrays with repeated values. JSON encoding is sufficiently fast that Perl function calling overhead tends to dominate for smaller inputs, but I don't find that overhead very interesting. -Also worth noting that JSON::SIMD formatting code is forked from JSON::XS, the -SIMD parts are only used for parsing. +Also worth noting that L formatting code is forked from +L, the SIMD parts are only used for parsing. API object from L documentation. Encode Canonical Decode JSON::PP 5312/s 5119/s 1290/s JSON::Tiny 7757/s - 3426/s - Cpanel::JSON::XS 108187/s 101867/s 103575/s + Cpanel::JSON::XS 114802/s 104141/s 107274/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 + FU::Util 132890/s 111630/s 121124/s Object (small) Encode Canonical Decode JSON::PP 907/s 829/s 202/s JSON::Tiny 1224/s - 499/s - Cpanel::JSON::XS 43168/s 28114/s 19229/s + Cpanel::JSON::XS 45732/s 30862/s 20102/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 + FU::Util 43853/s 26568/s 20426/s Object (large) Encode Canonical Decode JSON::PP 927/s 747/s 104/s JSON::Tiny 1108/s - 392/s - Cpanel::JSON::XS 29672/s 12637/s 16609/s + Cpanel::JSON::XS 30587/s 11875/s 15515/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 + FU::Util 36455/s 11920/s 17370/s Object (large, mixed unicode) Encode Canonical Decode JSON::PP 817/s 679/s 86/s JSON::Tiny 1036/s - 402/s - Cpanel::JSON::XS 20437/s 1345/s 7408/s + Cpanel::JSON::XS 25333/s 1459/s 7480/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 + FU::Util 33085/s 12639/s 9375/s Small integers Encode Decode JSON::PP 113/s 29/s JSON::Tiny 160/s 86/s - Cpanel::JSON::XS 7137/s 6083/s + Cpanel::JSON::XS 7345/s 6151/s JSON::SIMD 7963/s 4361/s JSON::XS 7915/s 6058/s - FU::Util 8565/s 5639/s + FU::Util 7883/s 5671/s Large integers Encode Decode JSON::PP 2176/s 329/s JSON::Tiny 2999/s 1638/s - Cpanel::JSON::XS 31302/s 48892/s + Cpanel::JSON::XS 32545/s 50162/s JSON::SIMD 37201/s 51719/s JSON::XS 36722/s 50110/s - FU::Util 116188/s 62110/s + FU::Util 110210/s 61006/s ASCII strings Encode Decode JSON::PP 2934/s 336/s JSON::Tiny 4126/s 1439/s - Cpanel::JSON::XS 116744/s 43489/s + Cpanel::JSON::XS 116721/s 44560/s JSON::SIMD 134711/s 50429/s JSON::XS 135419/s 43976/s - FU::Util 182026/s 44312/s + FU::Util 164804/s 48163/s Unicode strings Encode Decode JSON::PP 5113/s 253/s JSON::Tiny 6603/s 2585/s - Cpanel::JSON::XS 91704/s 64489/s + Cpanel::JSON::XS 97039/s 67669/s JSON::SIMD 106928/s 102440/s JSON::XS 105473/s 60558/s - FU::Util 217135/s 58972/s + FU::Util 187489/s 61121/s String escaping (few) Encode Decode JSON::PP 4251/s 352/s JSON::Tiny 4704/s 1869/s - Cpanel::JSON::XS 131789/s 106306/s + Cpanel::JSON::XS 136755/s 118059/s JSON::SIMD 158171/s 153692/s JSON::XS 157261/s 97676/s - FU::Util 191699/s 91177/s + FU::Util 216443/s 96354/s String escaping (many) Encode Decode JSON::PP 2224/s 366/s JSON::Tiny 2884/s 984/s - Cpanel::JSON::XS 136583/s 100789/s + Cpanel::JSON::XS 140220/s 107040/s JSON::SIMD 152951/s 113242/s JSON::XS 153471/s 106269/s - FU::Util 142604/s 97984/s + FU::Util 153081/s 100279/s =head2 XML Writing +L is the only XS-based XML DSL that I'm aware of, so all direct +competition is inherently slower by virtue of being pure perl. I'm sure some +templating modules will perform better, though. + HTML fragment TUWF::XML 795/s XML::Writer 833/s HTML::Tiny 423/s - FU::XMLWriter 5285/s + FU::XMLWriter 5396/s + + + +=head2 PostgreSQL client + +Fetching query results is highly unlikely to be a bottleneck in your code, this +benchmark is mainly here to verify that L is not introducing a +bottleneck where there shouldn't be one. + +Fetch and bitwise-or 20k integers + + Smallint Bigint + DBD::Pg 194/s 22/s + Pg::PQ 226/s 19/s + FU::Pg (bin) 239/s 23/s + FU::Pg (text) 222/s 21/s =cut # Cached data used by bench.PL. Same as the formatted tables above but easier to parse. -json/api Canonical Cpanel::JSON::XS 101867 -json/api Canonical FU::Util 113275 +json/api Canonical Cpanel::JSON::XS 104141 +json/api Canonical FU::Util 111630 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 Cpanel::JSON::XS 107274 +json/api Decode FU::Util 121124 json/api Decode JSON::PP 1290 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 Cpanel::JSON::XS 114802 +json/api Encode FU::Util 132890 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 Cpanel::JSON::XS 50162 +json/intl Decode FU::Util 61006 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 Cpanel::JSON::XS 32545 +json/intl Encode FU::Util 110210 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 Cpanel::JSON::XS 6151 +json/ints Decode FU::Util 5671 json/ints Decode JSON::PP 29 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 Cpanel::JSON::XS 7345 +json/ints Encode FU::Util 7883 json/ints Encode JSON::PP 113 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 Cpanel::JSON::XS 11875 +json/objl Canonical FU::Util 11920 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 Cpanel::JSON::XS 15515 +json/objl Decode FU::Util 17370 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 Cpanel::JSON::XS 30587 +json/objl Encode FU::Util 36455 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 Cpanel::JSON::XS 30862 +json/objs Canonical FU::Util 26568 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 Cpanel::JSON::XS 20102 +json/objs Decode FU::Util 20426 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 Cpanel::JSON::XS 45732 +json/objs Encode FU::Util 43853 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 Cpanel::JSON::XS 1459 +json/obju Canonical FU::Util 12639 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 Cpanel::JSON::XS 7480 +json/obju Decode FU::Util 9375 json/obju Decode JSON::PP 86 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 Cpanel::JSON::XS 25333 +json/obju Encode FU::Util 33085 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 Cpanel::JSON::XS 107040 +json/strel Decode FU::Util 100279 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 Cpanel::JSON::XS 140220 +json/strel Encode FU::Util 153081 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 Cpanel::JSON::XS 118059 +json/stres Decode FU::Util 96354 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 Cpanel::JSON::XS 136755 +json/stres Encode FU::Util 216443 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 Cpanel::JSON::XS 44560 +json/strs Decode FU::Util 48163 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 Cpanel::JSON::XS 116721 +json/strs Encode FU::Util 164804 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 Cpanel::JSON::XS 67669 +json/stru Decode FU::Util 61121 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 Cpanel::JSON::XS 97039 +json/stru Encode FU::Util 187489 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 +pg/ints Bigint DBD::Pg 22 +pg/ints Bigint FU::Pg (bin) 23 +pg/ints Bigint FU::Pg (text) 21 +pg/ints Bigint Pg::PQ 19 +pg/ints Smallint DBD::Pg 194 +pg/ints Smallint FU::Pg (bin) 239 +pg/ints Smallint FU::Pg (text) 222 +pg/ints Smallint Pg::PQ 226 +xml/a Rate FU::XMLWriter 5396 xml/a Rate HTML::Tiny 423 xml/a Rate TUWF::XML 795 xml/a Rate XML::Writer 833 diff --git a/bench.PL b/bench.PL index fa53068..6ccd763 100755 --- a/bench.PL +++ b/bench.PL @@ -25,7 +25,10 @@ my %modules = map +($_, eval "require $_; \$${_}::VERSION"), qw/ TUWF::XML HTML::Tiny XML::Writer + DBD::Pg + Pg::PQ /; +use FU::Pg; my %data; # "id x y" => { id x y rate exists } my %oldmodules; @@ -196,6 +199,32 @@ def 'xml/a', 'HTML fragment', [ 'Rate' ], +{ + die "FU_TEST_DB not set.\n" if !$ENV{FU_TEST_DB}; + my $pq = Pg::PQ::Conn->new($ENV{FU_TEST_DB}); + my $fu = FU::Pg->connect($ENV{FU_TEST_DB}); + # XXX: Doesn't support all connection params this way + my $dbi = DBI->connect("dbi:Pg:dbname=".$pq->db, $pq->user, $pq->pass, {RaiseError => 1, PrintError => 0}); + + my $small = 'SELECT x, x+1, x+2, x+3, x+4, x+5, x+6, x+7, x+8, x+9 FROM generate_series(-10000::smallint, 9999, 10) x(x)'; + my $big = 'SELECT x<<5, x<<10, x<<15, x<<20, x<<25, x<<30, x<<35, x<<40, x<<45, x<<50 FROM generate_series(1::bigint, 20000, 1) x(x)'; + + my sub dbi { my $sum = 0; my $st = $dbi->prepare_cached($_[0]); for my $row ($dbi->selectall_arrayref($st)->@*) { $sum ^= $_ for @$row; } } + my sub pq { my $sum = 0; $pq->prepare('' => $_[0]); for my $row ($pq->execQueryPrepared('')->rows) { $sum ^= $_ for @$row; } } + my sub fub { my $sum = 0; for my $row ($fu->q($_[0])->alla->@*) { $sum ^= $_ for @$row; } } + my sub fut { my $sum = 0; for my $row ($fu->q($_[0])->text->alla->@*) { $sum ^= $_ for @$row; } } + + def 'pg/ints', 'Fetch and bitwise-or 20k integers', [ 'Smallint', 'Bigint' ], + [ 'DBD::Pg', undef, sub { dbi($small) }, sub { dbi($big) } ], + [ 'Pg::PQ', undef, sub { pq($small) }, sub { pq($big) } ], + [ 'FU::Pg (bin)', 'FU', sub { fub($small) }, sub { fub($big) } ], + [ 'FU::Pg (text)', 'FU', sub { fut($small) }, sub { fut($big) } ]; +} + + + + + delete @data{ grep !$data{$_}{exists}, keys %data }; sub fmtbench($id, $text, $xs, $ys) { @@ -276,15 +305,27 @@ These benchmarks run on large-ish arrays with repeated values. JSON encoding is sufficiently fast that Perl function calling overhead tends to dominate for smaller inputs, but I don't find that overhead very interesting. -Also worth noting that JSON::SIMD formatting code is forked from JSON::XS, the -SIMD parts are only used for parsing. +Also worth noting that L formatting code is forked from +L, the SIMD parts are only used for parsing. :benches ^json %head2 XML Writing +L is the only XS-based XML DSL that I'm aware of, so all direct +competition is inherently slower by virtue of being pure perl. I'm sure some +templating modules will perform better, though. + :benches ^xml +%head2 PostgreSQL client + +Fetching query results is highly unlikely to be a bottleneck in your code, this +benchmark is mainly here to verify that L is not introducing a +bottleneck where there shouldn't be one. + +:benches ^pg + %cut # Cached data used by bench.PL. Same as the formatted tables above but easier to parse.