1#! /usr/bin/perl
2##
3## vi:ts=4:et
4##
5##---------------------------------------------------------------------------##
6##
7##  Author:
8##      Markus F.X.J. Oberhumer         <markus@oberhumer.com>
9##
10##  Description:
11##      Convert the output of the LZO lzotest program into a nice table.
12##
13##  Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
14##
15##---------------------------------------------------------------------------##
16
17$PROG = $0;
18require 'ctime.pl';
19
20#
21# get options
22#
23
24while ($_ = $ARGV[ $[ ], /^-/) {
25    shift(@ARGV);
26    /^--$/ && ($opt_last = 1, last);
27
28    /^--sort=name/ && ($opt_sort_summary_by_name++, next);
29    /^--sort=ratio/ && ($opt_sort_summary_by_ratio++, next);
30    /^-s/ && ($opt_summary_only++, next);
31    /^-t/ && ($opt_clear_time++, next);
32}
33
34
35$alg = '';
36$sep = "+" . ("-" x 76) . "+\n";
37
38$block_size = -1;
39
40$n = 0;
41@algs = ();
42%average = ();
43%total = ();
44
45$lzo_version_string = '';
46$lzo_version_date = '';
47
48
49# /***********************************************************************
50# //
51# ************************************************************************/
52
53while (<>) {
54
55    if (/(^|\s)(\d+)\s+block\-size/i) {
56        if ($block_size < 0) {
57            $block_size = $2;
58            &intro($block_size);
59        } elsif ($block_size != $2) {
60            die "$PROG: block-size: $block_size != $2\n";
61        }
62        next;
63    }
64
65    if (/^\s*LZO\s.*library\s+\(v\s*([\w\.\s]+)\s*\,\s*([^\)]+)\)/) {
66        $lzo_version_string = $1;
67        $lzo_version_date = $2;
68        next;
69    }
70
71    if (/^\s*(\S+(\s+\[\S+\])?)\s*(\|.*\|)\s*$/i) {
72        if ($1 ne $alg) {
73            &footer($1);
74            &header($1);
75        }
76        $line = $3;
77        &stats(*line);
78        print "$line\n" if (!$opt_summary_only);
79    }
80}
81&footer($1);
82
83&summary();
84
85exit(0);
86
87
88# /***********************************************************************
89# //
90# ************************************************************************/
91
92sub stats {
93    local (*l) = @_;
94    local ($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8);
95
96    if ($l !~ /^\|\s*(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d\.]+\s+)?([\d\.]+\s+)?([\d\.]+)\s+([\d\.]+)\s*\|/) {
97        die $_;
98    }
99
100    $n++;
101
102    $x1 = $1; $x2 = $2; $x3 = $3; $x4 = $4;
103    $x5 = ($x2 > 0) ? $x4 * 100.0 / $x2 : 0.0;
104    $x6 = ($x2 > 0) ? $x4 *   8.0 / $x2 : 0.0;
105    $x7 = $7; $x8 = $8;
106
107    # convert from kB/s to MB/s (for old versions of lzotest)
108    if ($x7 =~ /\.\d\d$/) { $x7 = $x7 / 1000.0; }
109    if ($x8 =~ /\.\d\d$/) { $x8 = $x8 / 1000.0; }
110
111    if ($opt_clear_time) {
112        $x7 = $x8 = 0.0;
113    }
114
115    $s[0] += $x2;
116    $s[1] += $x3;
117    $s[2] += $x4;
118    $s[3] += $x5;
119    $s[4] += $x6;
120    if ($x7 > 0) {
121        $s[5] += 1.0 / $x7; $sn[5] += 1;
122    }
123    if ($x8 > 0) {
124        $s[6] += 1.0/ $x8; $sn[6] += 1;
125    }
126
127    $x1 =~ s/\s+$//;
128    $l = sprintf("| %-14s %10d %5d %9d %6.1f %5.2f %9.3f %9.3f |",
129                    $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8);
130}
131
132
133# /***********************************************************************
134# //
135# ************************************************************************/
136
137sub header {
138    local ($t) = @_;
139
140    $alg = $t;
141
142    # reset stats
143    $n = 0;
144    @s = (0, 0, 0, 0.0, 0.0, 0.0, 0.0);
145    @sn = (0, 0, 0, 0, 0, 0, 0);
146
147    return if $opt_summary_only;
148
149    print "\n$alg\n\n";
150    print $sep;
151print <<EndOfString;
152| File Name          Length   CxB    ComLen  Ratio% Bits  Com MB/s  Dec MB/s |
153| ---------          ------   ---    ------  -----  ----  --------  -------- |
154EndOfString
155}
156
157
158# /***********************************************************************
159# //
160# ************************************************************************/
161
162sub footer {
163    local ($t) = @_;
164    local ($shm5, $shm6);
165
166    return unless $alg;
167    die if $n <= 0;
168    die if $s[0] <= 0;
169
170    # harmonic mean
171    $shm5 = $s[5] > 0 ? $sn[5] / $s[5] : 0.0;
172    $shm6 = $s[6] > 0 ? $sn[6] / $s[6] : 0.0;
173
174    push(@algs,$alg);
175
176    $average{$alg} =
177        sprintf("| %-14s %10d %5d %9d %6.1f %5.2f %9.3f %9.3f |\n",
178            "Average", $s[0]/$n, $s[1]/$n, $s[2]/$n,
179            $s[3]/$n, $s[4]/$n,
180            $shm5, $shm6);
181
182    $total{$alg} =
183        sprintf("| %-14s %10d %5d %9d %6.1f %5.2f %9.3f %9.3f |\n",
184            "Total", $s[0], $s[1], $s[2],
185            $s[2]/$s[0]*100, $s[2]/$s[0]*8,
186            $shm5, $shm6);
187
188    return if $opt_summary_only;
189
190    print $sep;
191    print $average{$alg};
192    print $total{$alg};
193    print $sep, "\n";
194}
195
196
197# /***********************************************************************
198# //
199# ************************************************************************/
200
201$sort_mode = 0;
202
203sub cmp_by_ratio {
204    local ($aa, $bb);
205
206    if ($sort_mode == 0) {
207        $aa = $average{$a};
208        $bb = $average{$b};
209    } elsif ($sort_mode == 1) {
210        $aa = $total{$a};
211        $bb = $total{$b};
212    } else {
213        die;
214    }
215
216    ($aa =~ m%^\s*\|\s+\S+\s+\d+\s+\d+\s+\d+\s+(\S+)%) || die;
217    $aa = $1;
218    ($bb =~ m%^\s*\|\s+\S+\s+\d+\s+\d+\s+\d+\s+(\S+)%) || die;
219    $bb = $1;
220
221    # $aa < $bb;
222    $aa cmp $bb;
223}
224
225
226# /***********************************************************************
227# //
228# ************************************************************************/
229
230sub summary {
231    local ($l);
232    local (@k);
233
234    $sort_mode = 0;
235    if ($opt_sort_summary_by_name) {
236        @k = sort(@algs);
237    } elsif ($opt_sort_summary_by_ratio) {
238        @k = sort(cmp_by_ratio @algs);
239    } else {
240        @k = @algs;
241    }
242
243    print "\n\n";
244    print "Summary of average values\n\n";
245    print $sep;
246print <<EndOfString;
247| Algorithm          Length   CxB    ComLen  Ratio% Bits  Com MB/s  Dec MB/s |
248| ---------          ------   ---    ------  -----  ----  --------  -------- |
249EndOfString
250
251    for (@k) {
252        $l = $average{$_};
253        $l =~ s/Average[\s]{7}/sprintf("%-14s",$_)/e;
254        print $l;
255    }
256    print $sep;
257
258
259
260    $sort_mode = 1;
261    if ($opt_sort_summary_by_name) {
262        @k = sort(@algs);
263    } elsif ($opt_sort_summary_by_ratio) {
264        @k = sort(cmp_by_ratio @algs);
265    } else {
266        @k = @algs;
267    }
268
269    print "\n\n";
270    print "Summary of total values\n\n";
271    print $sep;
272print <<EndOfString;
273| Algorithm          Length   CxB    ComLen  Ratio% Bits  Com MB/s  Dec MB/s |
274| ---------          ------   ---    ------  -----  ----  --------  -------- |
275EndOfString
276
277    for (@k) {
278        $l = $total{$_};
279        $l =~ s/Total[\s]{9}/sprintf("%-14s",$_)/e;
280        print $l;
281    }
282    print $sep;
283}
284
285
286# /***********************************************************************
287# //
288# ************************************************************************/
289
290sub intro {
291    local ($bs) = @_;
292    local ($v, $t, $x);
293    local ($u, $uname_m, $uname_s, $uname_r);
294
295    $t = &ctime(time); chop($t);
296    $t = sprintf("%-55s |", $t);
297
298    $v='';
299    if ($lzo_version_string) {
300        $v = $lzo_version_string;
301        $v .= ', ' . $lzo_version_date if $lzo_version_date;
302        $v = sprintf("%-55s |", $v);
303        $v = sprintf("| LZO version      : %s\n", $v);
304    }
305
306    if ($bs % 1024 == 0) {
307        $x = sprintf("%d (= %d kB)", $bs, $bs / 1024);
308    } else {
309        $x = sprintf("%d (= %.3f kB)", $bs, $bs / 1024.0);
310    }
311    $x = sprintf("%-55s |", $x);
312
313    $u='';
314    if (1 == 1) {
315        $uname_s = `uname -s`; $uname_s =~ s/^\s+//; $uname_s =~ s/\s+$//;
316        $uname_r = `uname -r`; $uname_r =~ s/^\s+//; $uname_r =~ s/\s+$//;
317        $uname_m = `uname -m`; $uname_m =~ s/^\s+//; $uname_m =~ s/\s+$//;
318        if ($uname_s && $uname_m) {
319            $u = $uname_s;
320            $u .= ' ' . $uname_r if $uname_r;
321            $u .= ' ' . $uname_m;
322            $u = sprintf("%-55s |", $u);
323            $u = sprintf("| Operating system : %s\n", $u);
324        }
325    }
326    print <<EndOfString;
327
328+----------------------------------------------------------------------------+
329| DATA COMPRESSION TEST                                                      |
330| =====================                                                      |
331| Time of run      : $t
332$v$u| Context length   : $x
333+----------------------------------------------------------------------------+
334
335
336Notes:
337- CxB is the number of independent blocks a file was splitted
338- MB/s is the speed measured in 1,000,000 uncompressed bytes per second
339- all averages are calculated from the un-rounded values
340- the average ratio & bits are calculated by the arithmetic mean
341- the average speed is calculated by the harmonic mean
342
343
344EndOfString
345}
346
347__END__
348
349
350### insert something like this after 'Time of run':
351
352| Hardware         : Intel Pentium 133, 64 MB RAM, 256 kB Cache          |
353| Operating system : MS-DOS 7.10, HIMEM.SYS 3.95, DOS/4GW 1.97           |
354| Compiler         : Watcom C32 10.5                                     |
355| Compiler flags   : -mf -5r -oneatx                                     |
356| Test suite       : Calgary Corpus Suite                                |
357| Files in suite   : 14                                                  |
358| Timing accuracy  : One part in 100                                     |
359
360
361