1#! @PERL@ 2# 3# $Id:$ 4# 5# Created By Tobi Oetiker <tobi@oetiker.ch> 6# Date 2006-10-27 7# 8#makes program work AFTER install 9 10my $Chunk = shift @ARGV || 10000; 11 12use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch @prefix@/lib/perl ); 13 14print <<NOTE; 15 16RRDtool Performance Tester 17-------------------------- 18Running on $RRDs::VERSION; 19 20RRDtool update performance is ultimately disk-bound. Since very little data 21does actually get written to disk in a single update, the performance 22is highly dependent on the cache situation of your machine. 23 24This test tries to cater for this. It works like this: 25 261) Create $Chunk RRD files in a tree 27 282) For $Chunk -> Update RRD file, Sync 29 303) goto 1) 31 32The numbers at the start of the row, show which 33RRA is being updated. So if several RRAs are being updated, 34you should see a slowdown as data has to be read from disk. 35 36The growing number in the second column shows how many RRD have been 37updated ... If everything is in cache, the number will Jump to $Chunk almost 38immediately. Then the system will seem to hang as 'sync' runs, to make sure 39all data has been written to disk prior to the next perftest run. This may 40not be 100% real-life, so you may want to remove the sync just for fun 41(then it is even less real-life, but different) 42 43NOTE 44 45use strict; 46use Time::HiRes qw(time); 47use RRDs; 48use IO::File; 49use Time::HiRes qw( usleep ); 50 51sub create($$){ 52 my $file = shift; 53 my $time = shift; 54 my $start = time; #since we loaded HiRes 55 RRDs::create ( $file.".rrd", "-b$time", qw( 56 -s300 57 DS:in:GAUGE:400:U:U 58 DS:out:GAUGE:400:U:U 59 RRA:AVERAGE:0.5:1:600 60 RRA:AVERAGE:0.5:6:600 61 RRA:MAX:0.5:6:600 62 RRA:AVERAGE:0.5:24:600 63 RRA:MAX:0.5:24:600 64 RRA:AVERAGE:0.5:144:600 65 RRA:MAX:0.5:144:600 66 )); 67 my $total = time - $start; 68 my $error = RRDs::error; 69 die $error if $error; 70 return $total; 71} 72 73sub update($$){ 74 my $file = shift; 75 my $time = shift; 76 my $in = rand(1000); 77 my $out = rand(1000); 78 my $start = time; 79 my $ret = RRDs::updatev($file.".rrd", $time.":$in:$out"); 80 my $total = time - $start; 81 my $error = RRDs::error; 82 die $error if $error; 83 return $total; 84} 85 86sub tune($){ 87 my $file = shift; 88 my $start = time; 89 RRDs::tune ($file.".rrd", "-a","in:U","-a","out:U","-d","in:GAUGE","-d","out:GAUGE"); 90 my $total = time - $start; 91 my $error = RRDs::error; 92 die $error if $error; 93 return $total; 94} 95 96sub infofetch($){ 97 my $file = shift; 98 my $start = time; 99 my $info = RRDs::info ($file.".rrd"); 100 my $error = RRDs::error; 101 die $error if $error; 102 my $lasttime = $info->{last_update} - $info->{last_update} % $info->{step}; 103 my $fetch = RRDs::fetch ($file.".rrd",'AVERAGE','-s',$lasttime-1,'-e',$lasttime); 104 my $total = time - $start; 105 my $error = RRDs::error; 106 die $error if $error; 107 return $total; 108} 109 110sub stddev ($$$){ #http://en.wikipedia.org/wiki/Standard_deviation 111 my $sum = shift; 112 my $squaresum = shift; 113 my $count = shift; 114 return sqrt( 1 / $count * ( $squaresum - $sum*$sum / $count )) 115} 116 117sub makerrds($$$$){ 118 my $count = shift; 119 my $total = shift; 120 my $list = shift; 121 my $time = shift; 122 my @files; 123 my $now = int(time); 124 for (1..$count){ 125 my $id = sprintf ("%07d",$total); 126 $id =~ s/^(.)(.)(.)(.)(.)//; 127 push @$list, "$1/$2/$3/$4/$5/$id"; 128 -d "$1" or mkdir "$1"; 129 -d "$1/$2" or mkdir "$1/$2"; 130 -d "$1/$2/$3" or mkdir "$1/$2/$3"; 131 -d "$1/$2/$3/$4" or mkdir "$1/$2/$3/$4"; 132 -d "$1/$2/$3/$4/$5" or mkdir "$1/$2/$3/$4/$5"; 133 push @files, $list->[$total]; 134 create $list->[$total++],$time-2; 135 if ($now < int(time)){ 136 $now = int(time); 137 print STDERR "Creating RRDs: ", $count - $_," rrds to go. \r"; 138 } 139 } 140 return $count; 141} 142 143sub main (){ 144 mkdir "db-$$" or die $!; 145 chdir "db-$$"; 146 147 my $step = $Chunk; # number of rrds to creat for every round 148 149 my @path; 150 my $time=int(time); 151 152 my $tracksize = 0; 153 my $uppntr = 0; 154 155 156 my %squaresum = ( cr => 0, up => 0 ); 157 my %sum = ( cr => 0, up => 0 ); 158 my %count =( cr => 0, up => 0 ); 159 160 my $printtime = time; 161 my %step; 162 for (qw(1 6 24 144)){ 163 $step{$_} = int($time / 300 / $_); 164 } 165 166 for (0..2) { 167 # enhance the track 168 $time += 300; 169 $tracksize += makerrds $step,$tracksize,\@path,$time; 170 # run benchmark 171 172 for (0..50){ 173 $time += 300; 174 my $count = 0; 175 my $sum = 0; 176 my $squaresum = 0; 177 my $prefix = ""; 178 for (qw(1 6 24 144)){ 179 if (int($time / 300 / $_) > $step{$_}) { 180 $prefix .= "$_ "; 181 $step{$_} = int($time / 300 / $_); 182 } 183 else { 184 $prefix .= (" " x length("$_")) . " "; 185 } 186 } 187 my $now = int(time); 188 for (my $i = 0; $i<$tracksize;$i ++){ 189 my $ntime = int(time); 190 if ($now < $ntime or $i == $tracksize){ 191 printf STDERR "$prefix %7d \r",$i; 192 $now = $ntime; 193 } 194 my $elapsed = update($path[$i],$time); 195 $sum += $elapsed; 196 $squaresum += $elapsed**2; 197 $count++; 198 }; 199 my $startsync = time; 200 print STDERR 's'; 201 system "sync"; 202 print STDERR "\h"; 203 my $synctime = time-$startsync; 204 $sum += $synctime; 205 $squaresum += $synctime**2; 206 my $ups = $count/$sum; 207 my $sdv = stddev($sum,$squaresum,$count); 208 printf STDERR "$prefix %7d %6.0f Up/s (%6.5f sdv)\n",$count,$ups,$sdv; 209 } 210 print STDERR "\n"; 211 } 212} 213 214main; 215