| 1 | #!/usr/bin/env perl |
| 2 | use strict; |
| 3 | use warnings; |
| 4 | |
| 5 | package Time::Bench; |
| 6 | |
| 7 | use Time::HiRes; |
| 8 | |
| 9 | our ($sr, $su, $ss) = (0,0,0); #calibrators |
| 10 | |
| 11 | sub new { #constructor |
| 12 | my ($self, $ncalib) = @_; |
| 13 | $ncalib || $self->bench_calibrate(); |
| 14 | return $self; |
| 15 | } |
| 16 | |
| 17 | sub bench { |
| 18 | shift; |
| 19 | my $r0 = [Time::HiRes::gettimeofday()]; |
| 20 | my ($u0, $s0, $cu0, $cs0) = times; |
| 21 | qx{ @_ >/dev/null }; |
| 22 | my ($u, $s, $cu, $cs) = times; |
| 23 | my $r = Time::HiRes::tv_interval($r0); |
| 24 | #real, user, system |
| 25 | return($r-$sr, $cu-$cu0-($u-$u0)-$su, $cs-$cs0-($s-$s0)-$ss); |
| 26 | #return($r, $cu-$cu0-($u-$u0), $cs-$cs0-($s-$s0)); |
| 27 | #return($r-$sr, $cu-$cu0-$su, $cs-$cs0-$su); |
| 28 | #return($r, $cu-$cu0, $cs-$cs0); |
| 29 | } |
| 30 | |
| 31 | sub bench_multiple { |
| 32 | my ($this, $cmd, $times) = @_; |
| 33 | my ($ar, $au, $as) = (0,0,0); |
| 34 | print "\n==> Measuring: $cmd\n"; |
| 35 | for(my $i=1;$i<=$times;$i++) { |
| 36 | print " => run\t$i\t/$times\r"; |
| 37 | my ($r, $u, $s) = $this->bench($cmd); |
| 38 | $ar += $r; |
| 39 | $au += $u; |
| 40 | $as += $s; |
| 41 | } |
| 42 | print "\n => DONE!\n"; |
| 43 | return ($ar/$times, $au/$times, $as/$times); |
| 44 | } |
| 45 | |
| 46 | sub bench_print { |
| 47 | shift; |
| 48 | my ($r, $u, $s) = @_; |
| 49 | print "real\t $r\n", |
| 50 | "user\t $u\n", |
| 51 | "sys\t $s\n"; |
| 52 | |
| 53 | } |
| 54 | |
| 55 | sub bench_calibrate { |
| 56 | my ($this) = @_; |
| 57 | print "==> Calibrating..."; |
| 58 | ($sr, $su, $ss) = (0,0,0); |
| 59 | ($sr, $su, $ss) = $this->bench_multiple('true', 1000); |
| 60 | print " => Correction:\n"; |
| 61 | $this->bench_print($sr, $su, $ss); |
| 62 | return ($sr, $su, $ss); |
| 63 | } |
| 64 | |
| 65 | sub bench_sort { |
| 66 | my ($this, %hash) = @_; |
| 67 | my $i = 1; |
| 68 | foreach my $key (sort {$hash{$a} <=> $hash{$b} } keys %hash) { |
| 69 | print "$i.)\t$hash{$key}\t\t:\t$key\n"; |
| 70 | $i++; |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | sub bench_compare { |
| 75 | my ($this, $times, @cmds) = @_; |
| 76 | my (%r, %u, %s); |
| 77 | foreach(@cmds) { |
| 78 | ($r{$_}, $u{$_}, $s{$_}) = $this->bench_multiple($_, $times); |
| 79 | $this->bench_print($r{$_}, $u{$_}, $s{$_}); |
| 80 | } |
| 81 | return (\%r, \%u, \%s); |
| 82 | } |
| 83 | |
| 84 | sub bench_results { |
| 85 | my ($this, $r, $u, $s) = @_; |
| 86 | print "\n==> SORTED RESULTS!\n"; |
| 87 | print " => by Real time:\n"; |
| 88 | $this->bench_sort(%$r); |
| 89 | print " => by User time:\n"; |
| 90 | $this->bench_sort(%$u); |
| 91 | print " => by System time:\n"; |
| 92 | $this->bench_sort(%$s); |
| 93 | } |
| 94 | |
| 95 | package main; |
| 96 | |
| 97 | if($#ARGV < 0) { |
| 98 | print "$0 (CopyLefted by Harvie 2o1o)\n", |
| 99 | "\t- Compares execution times of given commands\n", |
| 100 | "\t- (You can compare multiple alghorithms to find the fastest one.)\n", |
| 101 | "\t- Usage:\t$0 <passes> <cmd1> [<cmd2> <cmd3> ...]\n", |
| 102 | "\t\t- passes: how many times i should measure (special calibration is done for values < 0)\n", |
| 103 | "\t\t- cmd1,cmd2,...: commands to compare\n", |
| 104 | "\n", |
| 105 | "\t- Example:\t$0 10 'sleep 1' 'sleep 2'\n", |
| 106 | "\t- Example:\t$0 100 'ls' 'ls -l'\n", |
| 107 | "\t- Example:\t$0 100 'ping google.com -c 1' 'ping yahoo.com -c 1'\n", |
| 108 | "\t- Example:\t$0 -1000 true false\n", |
| 109 | "\n"; |
| 110 | exit; |
| 111 | } |
| 112 | |
| 113 | my $times = shift @ARGV; |
| 114 | my $t = Time::Bench->new($times >= 0); #new(1) to disable calibration |
| 115 | my ($r, $u, $s) = $t->bench_compare(abs($times), @ARGV); |
| 116 | $t->bench_results($r, $u, $s); |
| 117 | |