1 #! @PERL@
2 #
3 # $Id:$
4 #
5 # Created By Tobi Oetiker <tobi@oetiker.ch>
6 # Date 2006-10-27
7 #
8 #makes programm work AFTER install
10 my $Chunk = shift @ARGV || 10000;
12 use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch @prefix@/lib/perl );
14 print <<NOTE;
16 RRDtool Performance Tester
17 --------------------------
18 Running on $RRDs::VERSION;
20 RRDtool update performance is ultimately disk-bound. Since very little data
21 does actually get written to disk in a single update, the performance
22 is highly dependent on the cache situation of your machine.
24 This test tries to cater for this. It works like this:
26 1) Create $Chunk RRD files in a tree
28 2) For $Chunk -> Update RRD file, Sync
30 3) goto 1)
32 The numbers at the start of the row, show which
33 RRA is being updated. So if several RRAs are being updated,
34 you should see a slowdown as data has to be read from disk.
36 The growning number in the second column shows how many RRD have been
37 updated ... If everything is in cache, the number will Jump to $Chunk almost
38 immediately. Then the system will seem to hang as 'sync' runs, to make sure
39 all data has been written to disk prior to the next perftest run. This may
40 not 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)
43 NOTE
45 use strict;
46 use Time::HiRes qw(time);
47 use RRDs;
48 use IO::File;
49 use Time::HiRes qw( usleep );
51 sub 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 }
73 sub 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 }
86 sub 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 }
96 sub 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 }
110 sub 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 }
117 sub 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 }
143 sub main (){
144 mkdir "db-$$" or die $!;
145 chdir "db-$$";
147 my $step = $Chunk; # number of rrds to creat for every round
149 my @path;
150 my $time=int(time);
152 my $tracksize = 0;
153 my $uppntr = 0;
156 my %squaresum = ( cr => 0, up => 0 );
157 my %sum = ( cr => 0, up => 0 );
158 my %count =( cr => 0, up => 0 );
160 my $printtime = time;
161 my %step;
162 for (qw(1 6 24 144)){
163 $step{$_} = int($time / 300 / $_);
164 }
166 for (0..2) {
167 # enhance the track
168 $time += 300;
169 $tracksize += makerrds $step,$tracksize,\@path,$time;
170 # run benchmark
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 }
214 main;