#!/usr/bin/python # Copyright 2011 Lars Wirzenius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import cliapp import ConfigParser import csv import os class SeivotToCsv(cliapp.Application): def add_settings(self): self.settings.add_string_setting(['output-dir'], 'write output files into DIR ' '(default: %default)', metavar='DIR', default='.') def process_args(self, args): seivots = [] for filename in args: seivots.append(self.read_seivot(filename)) sizes = self.find_initial_sizes(seivots) for size in sorted(sizes): group = self.find_seivots_in_size_group(seivots, size) group.sort(key=self.getkey) for op in ['backup', 'restore', 'list_files', 'forget']: filename = os.path.join(self.settings['output-dir'], '%s-%s.csv' % (op, size)) f = open(filename, 'wb') writer = csv.writer(f, lineterminator='\n') writer.writerow(['obnam', 'larch', 'gen0 time (s)', 'gen0 speed (Mbit/s)', 'gen0 RAM (MiB)', 'slowest inc (s)', 'slowest inc (Mbit/s)', 'largest RAM inc (MiB)']) for seivot in group: row = self.get_row_data(op, seivot) writer.writerow(row) f.close() def read_seivot(self, filename): cp = ConfigParser.ConfigParser() cp.read([filename]) return cp def getkey(self, seivot): return (seivot.get('meta', 'revision'), seivot.get('meta', 'larch-revision')) def get_size(self, seivot): return seivot.getint('0', 'backup.new-data') def find_initial_sizes(self, seivots): return list(set(self.get_size(s) for s in seivots)) def find_seivots_in_size_group(self, seivots, size): return [s for s in seivots if self.get_size(s) == size] def get_row_data(self, op, seivot): bytes = seivot.getint('0', '%s.new-data' % op) secs = seivot.getfloat('0', '%s.real' % op) slowest_inc = self.find_slowest_incremental(op, seivot) inc_bytes = seivot.getint(slowest_inc, '%s.new-data' % op) inc_secs = seivot.getfloat(slowest_inc, '%s.real' % op) row = ['r%s' % seivot.get('meta', 'revision'), 'r%s' % seivot.get('meta', 'larch-revision'), secs, self.bitspeed(bytes, secs), self.bytesize(seivot.getfloat('0', '%s.maxrss' % op)), inc_secs, self.bitspeed(inc_bytes, inc_secs), self.find_largest_incremental(op, seivot)] return row def values(self, op, suffix, seivot): for section in seivot.sections(): if section not in ['meta', '0']: yield section, seivot.getfloat(section, '%s.%s' % (op,suffix)) def find_slowest_incremental(self, op, seivot): v = list(self.values(op, 'real', seivot)) if not v: return '0' return min(v, key=lambda pair: pair[1])[0] def find_largest_incremental(self, op, seivot): v = self.values(op, 'maxrss', seivot) return self.bytesize(min(list(x[1] for x in v) or [0.0])) def bytesize(self, kilobytes): return '%.1f' % (float(kilobytes) / 1024) def bitspeed(self, bytes, seconds): return '%.1f' % (8*bytes / seconds / (1000**2)) if __name__ == '__main__': SeivotToCsv().run()