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