2 # ***** BEGIN LICENSE BLOCK *****
3 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 # The contents of this file are subject to the Mozilla Public License Version
6 # 1.1 (the "License"); you may not use this file except in compliance with
7 # the License. You may obtain a copy of the License at
8 # http://www.mozilla.org/MPL/
10 # Software distributed under the License is distributed on an "AS IS" basis,
11 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 # for the specific language governing rights and limitations under the
15 # The Original Code is Mozilla page-loader test, released Aug 5, 2001.
17 # The Initial Developer of the Original Code is
18 # Netscape Communications Corporation.
19 # Portions created by the Initial Developer are Copyright (C) 2001
20 # the Initial Developer. All Rights Reserved.
23 # John Morrison <jrgm@netscape.com>, original author
25 # Alternatively, the contents of this file may be used under the terms of
26 # either the GNU General Public License Version 2 or later (the "GPL"), or
27 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 # in which case the provisions of the GPL or the LGPL are applicable instead
29 # of those above. If you wish to allow use of your version of this file only
30 # under the terms of either the GPL or the LGPL, and not to allow others to
31 # use your version of this file under the terms of the MPL, indicate your
32 # decision by deleting the provisions above and replace them with the notice
33 # and other provisions required by the GPL or the LGPL. If you do not delete
34 # the provisions above, a recipient may use your version of this file under
35 # the terms of any one of the MPL, the GPL or the LGPL.
37 # ***** END LICENSE BLOCK *****
38 package URLTimingDataSet
;
40 use PageData
; # list of test pages, etc.
45 my $class = ref($proto) || $proto;
51 avgmedian
=> undef, # note: average of individual medians
55 $self->{id
} = shift || die "No id supplied";
56 $self->{table
} = shift || "t" . $self->{id
};
57 $self->{pages
} = PageData
->new;
58 bless ($self, $class);
68 # select the dataset from the db
71 for (my $i=0; $i < $self->{pages
}->length; $i++) {
72 my $name = $self->{pages
}->name($i);
76 foreach my $ref (@
{$self->{dataset
}}) {
77 next if ($name ne $ref->{content
});
79 if ($ref->{c_part
} eq "NaN") {
80 # we bailed out of this page load
85 my $s_intvl = $ref->{s_intvl
};
86 my $c_intvl = $ref->{c_intvl
};
87 my $errval = abs($s_intvl-$c_intvl)/(($s_intvl+$c_intvl)/2);
88 if ($errval > 0.08) { # one of them went wrong and stalled out (see [1] below)
89 $res = ($s_intvl <= $c_intvl) ?
$s_intvl : $c_intvl;
91 $res = int(($s_intvl + $c_intvl)/2);
97 my $avg = int(_avg
(@times));
98 my $med = _med
(@times);
99 my $max = $nan ?
"NaN" : _max
(@times);
100 my $min = _min
(@times);
101 push @
{$self->{results
}}, [ $i, $name, $count, $avg, $med, $max, $min, @times ];
104 $self->_get_summary();
105 $self->_sort_result_set();
112 my $dbh = DBI
->connect("DBI:CSV:f_dir=./db", {RaiseError
=> 1, AutoCommit
=> 1})
113 or die "Cannot connect: " . $DBI::errstr
;
116 SELECT INDEX
, S_INTVL
, C_INTVL
, C_PART
, CONTENT
, ID
118 WHERE ID
= '$self->{id}'
121 my $sth = $dbh->prepare($sql);
124 while (my @data = $sth->fetchrow_array()) {
125 push @
{$self->{dataset
}},
140 my (@avg, @med, @max, @min);
142 # how many pages were loaded in total ('sampled')
143 $self->{samples
} = scalar(@
{$self->{dataset
}});
145 # how many cycles (should I get this from test parameters instead?)
146 $self->{count
} = int(_avg
( map($_->[2], @
{$self->{results
}}) ));
147 #warn $self->{count};
149 # calculate overall average, average median, maximum, minimum, (RMS Error?)
150 for (@
{$self->{results
}}) {
156 $self->{average
} = int(_avg
(@avg));
157 $self->{avgmedian
} = int(_avg
(@med)); # note: averaging individual medians
158 $self->{maximum
} = _max
(@max);
159 $self->{minimum
} = _min
(@min);
162 sub _sort_result_set
{
164 # sort by median load time
165 # @{$self->{sorted}} = sort {$a->[4] <=> $b->[4]} @{$self->{results}};
166 # might be "NaN", but this is lame of me to be carrying around a string instead of undef
169 if ($a->[4] eq "NaN" || $b->[4] eq "NaN") {
170 return $a->[4] cmp $b->[4];
172 return $a->[4] <=> $b->[4];
174 } @
{$self->{results
}};
179 return $self->_as_string();
182 sub as_string_sorted
{
184 return $self->_as_string(@
{$self->{sorted
}});
190 my @ary = @_ ?
@_ : @
{$self->{results
}};
193 my ($index, $path, $count, $avg, $med, $max, $min, @times) = @
$_;
194 $str .= sprintf "%3s %-26s\t", $index, $path;
196 $str .= sprintf "%6s %6s %6s %6s ", $avg, $med, $max, $min;
197 foreach my $time (@times) {
198 $str .= sprintf "%6s ", $time;
207 # package internal helper functions
211 for (@_) { push @array, $_ if /^[+-]?\d+\.?\d*$/o; }
216 my @array = _num
(@_);
217 return "NaN" unless scalar(@array);
219 for (@array) { $sum += $_; }
220 return $sum/scalar(@array);
224 my @array = _num
(@_);
225 return "NaN" unless scalar(@array);
227 for (@array) { $max = ($max > $_) ?
$max : $_; }
232 my @array = _num
(@_);
233 return "NaN" unless scalar(@array);
235 for (@array) { $min = ($min < $_) ?
$min : $_; }
239 # returns the floor(N/2) element of a sorted ascending array
241 my @array = _num
(@_);
242 return "NaN" unless scalar(@array);
243 my $index = int((scalar(@array)-1)/2);
244 @array = sort {$a <=> $b} @array;
245 return $array[$index];
250 ################################################################################
252 # [1] in looking at the test results, in almost all cases, the
253 # round-trip time measured by the server logic and the client logic
254 # would be almost the same value (which is what one would
255 # expect). However, on occasion, one of the them would be "out of
256 # whack", and inconsistent with the additional "layout" measure by the
259 # i.e., a set of numbers like these:
260 # c_part c_intvl s_intvl
268 # which looks like the server side would stall in doing the accept or
269 # in running the mod-perl handler (possibly a GC?). (The following
270 # c_intvl would then be out of whack by a matching amount on the next
273 # At any rate, since it was clear from comparing with the 'c_part'
274 # measure, which of the times was bogus, I just use an arbitrary error
275 # measure to determine when to toss out the "bad" value.