| 1 | #!perl |
| 2 | |
| 3 | use warnings; |
| 4 | use strict; |
| 5 | use 5.014; |
| 6 | |
| 7 | use bytes (); |
| 8 | |
| 9 | use File::Slurp; |
| 10 | use Getopt::Long; |
| 11 | use Time::HiRes qw/ gettimeofday tv_interval /; |
| 12 | |
| 13 | use IO::Compress::Brotli; |
| 14 | use IO::Uncompress::Brotli; |
| 15 | |
| 16 | GetOptions( |
| 17 | 'd|decompress' => \(my $DECOMPRESS), |
| 18 | 'f|force' => \(my $FORCE), |
| 19 | 'h|help' => \(my $HELP), |
| 20 | 'i|input=s' => \(my $INPUT), |
| 21 | 'o|output=s' => \(my $OUTPUT), |
| 22 | 'q|quality=i' => \(my $QUALITY = 11), |
| 23 | 'r|repeat=i' => \(my $REPEAT = 1), |
| 24 | 's|stream=i' => \(my $STREAM), |
| 25 | 'v|verbose' => \(my $VERBOSE), |
| 26 | 'w|window=i' => \(my $WINDOW = 22), |
| 27 | ); |
| 28 | |
| 29 | if( $HELP ) { |
| 30 | say "Usage: $0 [--force] [--quality n] [--decompress] [--input filename] [--output filename]". |
| 31 | " [--repeat iters] [--verbose] [--window n] [--stream size]"; |
| 32 | exit 1; |
| 33 | } |
| 34 | |
| 35 | if( $REPEAT > 1 && !($INPUT && $OUTPUT) ) { |
| 36 | say "You can only run a benchmark on files specifying --input and --output"; |
| 37 | exit 1; |
| 38 | } |
| 39 | |
| 40 | my $t0 = [gettimeofday]; |
| 41 | my $total_size = 0; |
| 42 | my ($encoded, $decoded); |
| 43 | |
| 44 | for ( 1..$REPEAT ) { |
| 45 | my $ifh; |
| 46 | if( $INPUT ) { |
| 47 | open $ifh, "<", $INPUT |
| 48 | or die "Cannot open input file $INPUT.\n"; |
| 49 | } |
| 50 | $ifh //= \*STDIN; |
| 51 | binmode $ifh; |
| 52 | |
| 53 | my $ofh; |
| 54 | if( $OUTPUT ) { |
| 55 | die "Output file exists\n" |
| 56 | if( -e $OUTPUT && $REPEAT == 1 && !$FORCE ); |
| 57 | open $ofh, ">", $OUTPUT |
| 58 | or die "Cannot open output file $OUTPUT.\n"; |
| 59 | } |
| 60 | $ofh //= \*STDOUT; |
| 61 | binmode $ofh; |
| 62 | |
| 63 | if( $DECOMPRESS ) { |
| 64 | $STREAM //= 4 * 1024 * 1024; |
| 65 | my $bro = IO::Uncompress::Brotli->create(); |
| 66 | while( read $ifh, (my $buf), $STREAM ) { |
| 67 | $decoded = $bro->decompress($buf); |
| 68 | $total_size += bytes::length( $decoded ); |
| 69 | print $ofh $decoded; |
| 70 | } |
| 71 | } |
| 72 | else { |
| 73 | if( $STREAM ) { |
| 74 | my $bro = IO::Compress::Brotli->create(); |
| 75 | $bro->quality( $QUALITY ); |
| 76 | $bro->window( $WINDOW ); |
| 77 | while( read $ifh, (my $buf), $STREAM ) { |
| 78 | $encoded = $bro->compress($buf); |
| 79 | $total_size += bytes::length( $buf ); |
| 80 | print $ofh $encoded; |
| 81 | } |
| 82 | $encoded = $bro->finish(); |
| 83 | print $ofh $encoded; |
| 84 | } |
| 85 | else { |
| 86 | my $decoded = read_file( $ifh ); |
| 87 | my $encoded = bro( $decoded, $QUALITY, $WINDOW ); |
| 88 | $total_size += bytes::length( $decoded ); |
| 89 | write_file( $ofh, $encoded ); |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | if( $VERBOSE ) { |
| 95 | my $elapsed = tv_interval ( $t0 ); |
| 96 | say "Ran $REPEAT iterations in a total of $elapsed seconds"; |
| 97 | say sprintf( |
| 98 | "Brotli %s speed: %.6f MB/s", |
| 99 | ( $DECOMPRESS ? "decompression" : "compression" ), |
| 100 | $total_size / 1024 / 1024 / $elapsed |
| 101 | ); |
| 102 | } |