131 lines
3.7 KiB
Perl
Executable file
131 lines
3.7 KiB
Perl
Executable file
#!/usr/bin/perl
|
|
|
|
exit if @ARGV && @ARGV[0] eq 'bench';
|
|
|
|
# Can be invoked as:
|
|
# ./bench.PL # (or 'make bench') generates FU/Benchmarks.pod
|
|
# ./bench.PL regex # run benchmark(s) matching the regex
|
|
|
|
use v5.36;
|
|
use builtin 'true', 'false';
|
|
use Benchmark ':hireswallclock', 'timethis';
|
|
use Config;
|
|
|
|
my $modules = join '', map sprintf("=item L<%s> %s\n\n", $_, eval "require $_; \$${_}::VERSION"), qw/
|
|
FU
|
|
Cpanel::JSON::XS
|
|
JSON::PP
|
|
JSON::XS
|
|
JSON::SIMD
|
|
/;
|
|
|
|
|
|
my(%bench, @bench);
|
|
sub bench($name, @arg) {
|
|
push @bench, $name;
|
|
$bench{$name} = \@arg;
|
|
}
|
|
|
|
sub runbench($text, @f) {
|
|
print "$text\n\n";
|
|
|
|
# TODO: Should include variance; factor-compared-to-slowest might be cool too
|
|
for my ($t, $f) (@f) {
|
|
my $o = timethis -1, $f, 0, 'none';
|
|
printf " %18s%10d/s\n", $t, $o->iters/$o->real;
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
sub runbenches($re) {
|
|
runbench $bench{$_}->@* for grep /$re/, @bench;
|
|
}
|
|
|
|
|
|
|
|
|
|
# Use similar options for fair comparisons.
|
|
my $j_cp = Cpanel::JSON::XS->new->allow_nonref->unblessed_bool->convert_blessed;
|
|
my $j_pp = JSON::PP->new->allow_nonref->core_bools->convert_blessed;
|
|
my $j_xs = JSON::XS->new->allow_nonref->boolean_values([false,true])->convert_blessed;
|
|
my $j_si = JSON::SIMD->new->allow_nonref->core_bools->convert_blessed;
|
|
use FU::Util 'json_format';
|
|
|
|
sub jsonfmt($name, $text, $data) {
|
|
bench "jsonfmt/$name", $text,
|
|
'JSON::PP', sub { $j_pp->encode($data) },
|
|
'Cpanel::JSON::XS',sub { $j_cp->encode($data) },
|
|
'JSON::SIMD', sub { $j_si->encode($data) },
|
|
'JSON::XS', sub { $j_xs->encode($data) },
|
|
'FU::Util', sub { json_format $data };
|
|
}
|
|
|
|
# From JSON::XS POD.
|
|
jsonfmt api => 'API object from L<JSON::XS> documentation.',
|
|
[ map +{method => 'handleMessage', params => ['user1','we were just talking'], 'id' => undef, 'array' => [1,11,234,-5,1e5,1e7,1,0]}, 1..10 ];
|
|
|
|
jsonfmt ints => 'Small integers', [ -5000..5000 ];
|
|
jsonfmt intl => 'Large integers', [ map { my $n=$_; map +($n+1<<$_), 10..60 } 1..10 ];
|
|
jsonfmt strs => 'ASCII strings', [ map +('hello, world', 'one more string', 'another string'), 1..100 ];
|
|
jsonfmt stru => 'Unicode strings', do { use utf8;
|
|
[ map +('グリザイアの果実 -LE FRUIT DE LA GRISAIA-', '💩', 'Я люблю нічого не робити'), 1..50 ];
|
|
};
|
|
jsonfmt stres => 'String escaping (few)', [ map 'This string needs to "be escaped" a little bit', 1..100 ];
|
|
jsonfmt strel => 'String escaping (many)', [ map "This \" \\ needs \b\x01\x02\x03\x04 more", 1..100 ];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!@ARGV || $ARGV[0] eq 'bench') {
|
|
chomp(my $date = `date +%F`);
|
|
print "Writing to FU/Benchmarks.pod...\n";
|
|
open my $F, '>FU/Benchmarks.pod' or die $!;
|
|
select $F;
|
|
while (<DATA>) {
|
|
s/^:modules/$modules/;
|
|
s/^:benches (.+)/runbenches $1/e;
|
|
s/^:context/These benchmarks were performed on $date with perl $^V on $Config{archname}./;
|
|
print;
|
|
}
|
|
} else {
|
|
runbenches $_ for @ARGV;
|
|
}
|
|
|
|
__DATA__
|
|
=head1 NAME
|
|
|
|
FU::Benchmarks - A bunch of automated benchmark results.
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This file is automatically generated from 'bench.pl' in the L<FU> distribution.
|
|
These benchmarks compare performance of some FU functionality against similar
|
|
modules found on CPAN.
|
|
|
|
=head1 CONTEXT
|
|
|
|
:context
|
|
|
|
The following module versions were used:
|
|
|
|
=over
|
|
|
|
:modules
|
|
|
|
=back
|
|
|
|
=head1 BENCHMARKS
|
|
|
|
=head2 JSON Formatting
|
|
|
|
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. Other modules
|
|
will likely do better in benchmarks on small inputs.
|
|
|
|
Also worth noting that JSON::SIMD formatting code is forked from JSON::XS, the
|
|
SIMD parts are only used for parsing.
|
|
|
|
:benches ^jsonfmt
|