use strict;
use 5.014;
+use bytes;
+
use File::Slurp;
use Getopt::Long;
+use Time::HiRes qw/ gettimeofday tv_interval /;
use IO::Compress::Brotli;
use IO::Uncompress::Brotli;
GetOptions(
'c|custom-dictionary=s' => \(my $DICTIONARY),
'd|decompress' => \(my $DECOMPRESS),
+ 'f|force' => \(my $FORCE),
'h|help' => \(my $HELP),
'i|input=s' => \(my $INPUT),
'o|output=s' => \(my $OUTPUT),
'q|quality=i' => \(my $QUALITY = 11),
- 'r|repeat=i' => \(my $REPEAT),
+ 'r|repeat=i' => \(my $REPEAT = 1),
's|stream=i' => \(my $STREAM),
'v|verbose' => \(my $VERBOSE),
'w|window=i' => \(my $WINDOW = 22),
exit 1;
}
-my ($ifh, $ofh) = (\*STDIN, \*STDOUT);
-
-if( $INPUT ) {
- open $ifh, "<", $INPUT
- or die "Cannot open input file $INPUT.\n";
+if( $REPEAT > 1 && !($INPUT && $OUTPUT) ) {
+ say "You can only run a benchmark on files specifying --input and --output";
+ exit 1;
}
-binmode $ifh;
-if( $OUTPUT ) {
- open $ofh, ">", $OUTPUT
- or die "Cannot open output file $OUTPUT.\n";
-}
-binmode $ofh;
+my $t0 = [gettimeofday];
+my $total_size = 0;
+my ($encoded, $decoded);
-if( $DECOMPRESS ) {
- if( $STREAM ) {
- my $brotli = IO::Uncompress::Brotli->create();
- while( read $ifh, (my $buf), $STREAM ) {
- print $ofh $brotli->decompress($buf);
- }
+for ( 1..$REPEAT ) {
+ my $ifh;
+ if( $INPUT ) {
+ open $ifh, "<", $INPUT
+ or die "Cannot open input file $INPUT.\n";
}
- else {
- my $encoded = read_file( $ifh );
- my $decoded = unbro( $encoded );
- write_file( $ofh, $decoded );
+ $ifh //= \*STDIN;
+ binmode $ifh;
+
+ my $ofh;
+ if( $OUTPUT ) {
+ die "Output file exists"
+ if( -e $OUTPUT && $REPEAT == 1 && !$FORCE );
+ open $ofh, ">", $OUTPUT
+ or die "Cannot open output file $OUTPUT.\n";
}
-}
-else {
- if( $STREAM ) {
- my $brotli = IO::Compress::Brotli->create();
- $brotli->quality( $QUALITY );
- $brotli->window( $WINDOW );
- while( read $ifh, (my $buf), $STREAM ) {
- print $ofh $brotli->compress($buf);
+ $ofh //= \*STDOUT;
+ binmode $ofh;
+
+ if( $DECOMPRESS ) {
+ if( $STREAM ) {
+ my $bro = IO::Uncompress::Brotli->create();
+ while( read $ifh, (my $buf), $STREAM ) {
+ $decoded = $bro->decompress($buf);
+ $total_size += bytes::length( $decoded );
+ print $ofh $decoded;
+ }
+ }
+ else {
+ $encoded = read_file( $ifh );
+ $decoded = unbro( $encoded );
+ $total_size += bytes::length( $decoded );
+ write_file( $ofh, $decoded );
}
}
else {
- my $decoded = read_file( $ifh );
- my $encoded = bro( $decoded, $QUALITY, $WINDOW );
- write_file( $ofh, $encoded );
+ if( $STREAM ) {
+ my $bro = IO::Compress::Brotli->create();
+ $bro->quality( $QUALITY );
+ $bro->window( $WINDOW );
+ while( read $ifh, (my $buf), $STREAM ) {
+ $encoded = $bro->compress($buf);
+ $total_size += bytes::length( $encoded );
+ print $ofh $encoded;
+ }
+ $encoded = $bro->finish();
+ $total_size += bytes::length( $encoded );
+ print $ofh $encoded;
+ }
+ else {
+ my $decoded = read_file( $ifh );
+ my $encoded = bro( $decoded, $QUALITY, $WINDOW );
+ $total_size += bytes::length( $encoded );
+ write_file( $ofh, $encoded );
+ }
}
}
+if( $VERBOSE ) {
+ my $elapsed = tv_interval ( $t0 );
+ say "Ran $REPEAT iterations in a total of $elapsed seconds";
+ say sprintf(
+ "Brotli %s speed: %.6f MB/s",
+ ( $DECOMPRESS ? "decompression" : "compression" ),
+ $total_size / 1024 / 1024 / $elapsed
+ );
+}