3 ## See the usage() function for operating instructions. ##
9 _re_trail
= re
.compile('\((?P<txn_body>[a-z_]*), (?P<filename>[a-z_\-./]*), (?P<lineno>[0-9]*), (?P<txn>0|1)\): (?P<ops>.*)')
10 _re_table_op
= re
.compile('\(([a-z]*), ([a-z]*)\)')
12 _seperator
= '------------------------------------------------------------\n'
14 def parse_trails_log(infile
):
17 for line
in infile
.readlines():
18 m
= _re_trail
.match(line
)
23 sys
.stderr
.write('Invalid input, line %u:\n%s\n' % (lineno
, line
))
26 txn
= int(m
.group('txn'))
28 ### We're not interested in trails that don't use txns at this point.
31 txn_body
= (m
.group('txn_body'), m
.group('filename'),
32 int(m
.group('lineno')))
33 trail
= _re_table_op
.findall(m
.group('ops'))
37 sys
.stderr
.write('Warning! Empty trail at line %u:\n%s' % (lineno
, line
))
39 trails
.append((txn_body
, trail
))
44 def output_summary(trails
, outfile
):
46 for (txn_body
, trail
) in trails
:
47 ops
.append(len(trail
))
50 total_trails
= len(ops
)
51 total_ops
= reduce(operator
.add
, ops
)
53 median_ops
= ops
[total_trails
/ 2]
54 average_ops
= float(total_ops
) / total_trails
56 outfile
.write(_seperator
)
57 outfile
.write('Summary\n')
58 outfile
.write(_seperator
)
59 outfile
.write('Total number of trails: %10i\n' % total_trails
)
60 outfile
.write('Total number of ops: %10i\n' % total_ops
)
61 outfile
.write('max ops/trail: %10i\n' % max_ops
)
62 outfile
.write('median ops/trail: %10i\n' % median_ops
)
63 outfile
.write('average ops/trail: %10.2f\n' % average_ops
)
67 # custom compare function
68 def _freqtable_cmp((a
, b
), (c
, d
)):
74 def list_frequencies(list):
76 Given a list, return a list composed of (item, frequency)
82 counter
[item
] = counter
.get(item
, 0) + 1
84 frequencies
= counter
.items()
85 frequencies
.sort(_freqtable_cmp
)
90 def output_trail_length_frequencies(trails
, outfile
):
92 for (txn_body
, trail
) in trails
:
93 ops
.append(len(trail
))
95 total_trails
= len(ops
)
96 frequencies
= list_frequencies(ops
)
98 outfile
.write(_seperator
)
99 outfile
.write('Trail length frequencies\n')
100 outfile
.write(_seperator
)
101 outfile
.write('ops/trail frequency percentage\n')
102 for (r
, f
) in frequencies
:
103 p
= float(f
) * 100 / total_trails
104 outfile
.write('%4i %6i %5.2f\n' % (r
, f
, p
))
108 def output_trail(outfile
, trail
, column
= 0):
109 ### Output the trail itself, in its own column
112 outfile
.write('<empty>\n')
118 if len(line
) + len(op_str
) > 75 - column
:
119 outfile
.write('%s,\n' % line
)
120 outfile
.write(''.join(' ' * column
))
123 line
= line
+ ', ' + op_str
124 outfile
.write('%s\n' % line
)
129 def output_trail_frequencies(trails
, outfile
):
131 total_trails
= len(trails
)
134 for (txn_body
, trail
) in trails
:
135 ttrails
.append((txn_body
, tuple(trail
)))
137 frequencies
= list_frequencies(ttrails
)
139 outfile
.write(_seperator
)
140 outfile
.write('Trail frequencies\n')
141 outfile
.write(_seperator
)
142 outfile
.write('frequency percentage ops/trail trail\n')
143 for (((txn_body
, file, line
), trail
), f
) in frequencies
:
144 p
= float(f
) * 100 / total_trails
145 outfile
.write('-- %s - %s:%u --\n' % (txn_body
, file, line
))
146 outfile
.write('%6i %5.2f %4i ' % (f
, p
, len(trail
)))
147 output_trail(outfile
, trail
, 37)
150 def output_txn_body_frequencies(trails
, outfile
):
152 for (txn_body
, trail
) in trails
:
153 bodies
.append(txn_body
)
155 total_trails
= len(trails
)
156 frequencies
= list_frequencies(bodies
)
158 outfile
.write(_seperator
)
159 outfile
.write('txn_body frequencies\n')
160 outfile
.write(_seperator
)
161 outfile
.write('frequency percentage txn_body\n')
162 for ((txn_body
, file, line
), f
) in frequencies
:
163 p
= float(f
) * 100 / total_trails
164 outfile
.write('%6i %5.2f %s - %s:%u\n'
165 % (f
, p
, txn_body
, file, line
))
170 w("%s: a program for analyzing Subversion trail usage statistics.\n" % pgm
)
174 w(" Compile Subversion with -DSVN_FS__TRAIL_DEBUG, which will cause it\n")
175 w(" it to print trail statistics to stderr. Save the stats to a file,\n")
176 w(" invoke %s on the file, and ponder the output.\n" % pgm
)
180 if __name__
== '__main__':
181 if len(sys
.argv
) > 2:
182 sys
.stderr
.write("Error: too many arguments\n\n")
186 if len(sys
.argv
) == 1:
190 infile
= open(sys
.argv
[1])
192 sys
.stderr
.write("Error: unable to open '%s'\n\n" % sys
.argv
[1])
196 trails
= parse_trails_log(infile
)
198 output_summary(trails
, sys
.stdout
)
199 output_trail_length_frequencies(trails
, sys
.stdout
)
200 output_trail_frequencies(trails
, sys
.stdout
)
201 output_txn_body_frequencies(trails
, sys
.stdout
)