#!/usr/bin/env python # # Copyright 2014 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 json import os import cliapp MiB = 2**20 GiB = 2**30 class ObnamBenchmarkSummary(cliapp.Application): columns = ( ('version', 'version'), ('ef-speed', 'EF files/s'), ('ef-repo-size', 'EF repo (MiB)'), ('lf-speed', 'LF MiB/s'), ('lf-repo-size', 'LF repo (MiB)'), ) def process_args(self, args): summaries = [] for dirname in args: summary = self.summarise_directory(dirname) summaries.append(summary) self.show_summaries(summaries) def summarise_directory(self, dirname): filename = os.path.join(dirname, 'benchmark.json') with open(filename) as f: obj = json.load(f) return { 'version': self.get_obnam_version(obj), 'ef-speed': '%.0f' % self.get_empty_files_speed(obj), 'ef-files': self.get_empty_files_count(obj), 'ef-repo-size': self.format_size(self.get_empty_files_repo_size(obj), MiB), 'lf-speed': self.format_size(self.get_large_file_speed(obj), MiB), 'lf-size': self.format_size(self.get_large_file_size(obj), GiB), 'lf-repo-size': self.format_size(self.get_large_file_repo_size(obj), MiB), } def get_obnam_version(self, obj): return obj['versions']['obnam-version'] def get_empty_files_speed(self, obj): count = self.get_empty_files_count(obj) step = self.find_step(obj, 'EmptyFiles', 'initial-backup') return count / step['duration'] def get_empty_files_count(self, obj): step = self.find_step(obj, 'EmptyFiles', 'create-live-data') return step['empty-files-count'] def get_empty_files_repo_size(self, obj): step = self.find_step(obj, 'EmptyFiles', 'initial-backup') return step['repo-size'] def get_large_file_speed(self, obj): file_size = self.get_large_file_size(obj) step = self.find_step(obj, 'SingleLargeFile', 'initial-backup') return file_size / step['duration'] def get_large_file_size(self, obj): step = self.find_step(obj, 'SingleLargeFile', 'create-live-data') return step['single-large-file-size'] def get_large_file_repo_size(self, obj): step = self.find_step(obj, 'SingleLargeFile', 'initial-backup') return step['repo-size'] def find_step(self, obj, benchmark_name, step_name): for step in obj['benchmarks'][benchmark_name]['steps']: if step['step'] == step_name: return step raise Exception('step %s not found' % step) def format_size(self, size, unit): return '%.0f' % (size / unit) def show_summaries(self, summaries): lines = [[title for key, title in self.columns]] for s in summaries: line = [str(s[key]) for key, title in self.columns] lines.append(line) widths = self.compute_column_widths(lines) titles = lines[0] results = sorted(lines[1:]) for line in [titles] + results: cells = [] for i, cell in enumerate(line): cells.append('%*s' % (widths[i], cell)) self.output.write(' | '.join(cells)) self.output.write('\n') def compute_column_widths(self, lines): widths = [] n = len(lines[0]) for col in range(n): width = 0 for line in lines: width = max(width, len(line[col])) widths.append(width) return widths if __name__ == '__main__': ObnamBenchmarkSummary().run()