+++ /dev/null
-#!/usr/bin/env python
-"""Compute basic stats about CBench data."""
-
-import csv
-import numpy
-import pprint
-import matplotlib.pyplot as pyplot
-import argparse
-import sys
-
-
-class Stats(object):
-
- """Compute stats and/or graph data.
-
- I know I could convert these fns that simply punt to a helper
- to a dict/list data structure, but that would remove some of the
- flexabilty I get by simply calling a graph/stat fn for each
- graph/stat arg. All current fns just punt to helpers, but future
- ones might not.
-
- """
-
- results_file = "results.csv"
- log_file = "cbench.log"
- precision = 3
- run_index = 0
- min_flow_index = 1
- max_flow_index = 2
- avg_flow_index = 3
- start_time_index = 4
- end_time_index = 5
- start_steal_time_index = 12
- end_steal_time_index = 13
- used_ram_index = 15
- one_load_index = 18
- five_load_index = 19
- fifteen_load_index = 20
- start_iowait_index = 22
- end_iowait_index = 23
-
- def __init__(self):
- """Setup some flags and data structures, kick off build_cols call."""
- self.build_cols()
- self.results = {}
- self.results["sample_size"] = len(self.run_col)
-
- def build_cols(self):
- """Parse results file into lists of values, one per column."""
- self.run_col = []
- self.min_flows_col = []
- self.max_flows_col = []
- self.avg_flows_col = []
- self.runtime_col = []
- self.used_ram_col = []
- self.iowait_col = []
- self.steal_time_col = []
- self.one_load_col = []
- self.five_load_col = []
- self.fifteen_load_col = []
-
- with open(self.results_file, "rb") as results_fd:
- results_reader = csv.reader(results_fd)
- for row in results_reader:
- try:
- self.run_col.append(float(row[self.run_index]))
- self.min_flows_col.append(float(row[self.min_flow_index]))
- self.max_flows_col.append(float(row[self.max_flow_index]))
- self.avg_flows_col.append(float(row[self.avg_flow_index]))
- self.runtime_col.append(float(row[self.end_time_index]) -
- float(row[self.start_time_index]))
- self.used_ram_col.append(float(row[self.used_ram_index]))
- self.iowait_col.append(float(row[self.end_iowait_index]) -
- float(row[self.start_iowait_index]))
- self.steal_time_col.append(
- float(row[self.end_steal_time_index]) -
- float(row[self.start_steal_time_index]))
- self.one_load_col.append(float(row[self.one_load_index]))
- self.five_load_col.append(float(row[self.five_load_index]))
- self.fifteen_load_col.append(
- float(row[self.fifteen_load_index]))
- except ValueError:
- # Skips header
- continue
-
- def compute_avg_flow_stats(self):
- """Compute CBench average flows/second stats."""
- self.compute_generic_stats("flows", self.avg_flows_col)
-
- def build_avg_flow_graph(self, total_gcount, graph_num):
- """Plot average flows/sec data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Average Flows per Second", self.avg_flows_col)
-
- def compute_min_flow_stats(self):
- """Compute CBench min flows/second stats."""
- self.compute_generic_stats("min_flows", self.min_flows_col)
-
- def build_min_flow_graph(self, total_gcount, graph_num):
- """Plot min flows/sec data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Minimum Flows per Second", self.min_flows_col)
-
- def compute_max_flow_stats(self):
- """Compute CBench max flows/second stats."""
- self.compute_generic_stats("max_flows", self.max_flows_col)
-
- def build_max_flow_graph(self, total_gcount, graph_num):
- """Plot max flows/sec data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Maximum Flows per Second", self.max_flows_col)
-
- def compute_ram_stats(self):
- """Compute used RAM stats."""
- self.compute_generic_stats("used_ram", self.used_ram_col)
-
- def build_ram_graph(self, total_gcount, graph_num):
- """Plot used RAM data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Used RAM (MB)", self.used_ram_col)
-
- def compute_runtime_stats(self):
- """Compute CBench runtime length stats."""
- self.compute_generic_stats("runtime", self.runtime_col)
-
- def build_runtime_graph(self, total_gcount, graph_num):
- """Plot CBench runtime length data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "CBench Runtime (sec)", self.runtime_col)
-
- def compute_iowait_stats(self):
- """Compute iowait stats."""
- self.compute_generic_stats("iowait", self.iowait_col)
-
- def build_iowait_graph(self, total_gcount, graph_num):
- """Plot iowait data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "IOWait Time (sec)", self.iowait_col)
-
- def compute_steal_time_stats(self):
- """Compute steal time stats."""
- self.compute_generic_stats("steal_time", self.steal_time_col)
-
- def build_steal_time_graph(self, total_gcount, graph_num):
- """Plot steal time data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Steal Time (sec)", self.steal_time_col)
-
- def compute_one_load_stats(self):
- """Compute one minute load stats."""
- self.compute_generic_stats("one_load", self.one_load_col)
-
- def build_one_load_graph(self, total_gcount, graph_num):
- """Plot one minute load data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "One Minute Load", self.one_load_col)
-
- def compute_five_load_stats(self):
- """Compute five minute load stats."""
- self.compute_generic_stats("five_load", self.five_load_col)
-
- def build_five_load_graph(self, total_gcount, graph_num):
- """Plot five minute load data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Five Minute Load", self.five_load_col)
-
- def compute_fifteen_load_stats(self):
- """Compute fifteen minute load stats."""
- self.compute_generic_stats("fifteen_load", self.fifteen_load_col)
-
- def build_fifteen_load_graph(self, total_gcount, graph_num):
- """Plot fifteen minute load data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
-
- """
- self.build_generic_graph(total_gcount, graph_num,
- "Fifteen Minute Load", self.fifteen_load_col)
-
- def compute_generic_stats(self, stats_name, stats_col):
- """Helper for computing generic stats."""
- generic_stats = {}
- generic_stats["min"] = int(numpy.amin(stats_col))
- generic_stats["max"] = int(numpy.amax(stats_col))
- generic_stats["mean"] = round(numpy.mean(stats_col), self.precision)
- generic_stats["stddev"] = round(numpy.std(stats_col), self.precision)
- try:
- generic_stats["relstddev"] = round(generic_stats["stddev"] /
- generic_stats["mean"] *
- 100, self.precision)
- except ZeroDivisionError:
- generic_stats["relstddev"] = 0.
- self.results[stats_name] = generic_stats
-
- def build_generic_graph(self, total_gcount, graph_num, y_label, data_col):
- """Helper for plotting generic data.
-
- :param total_gcount: Total number of graphs to render.
- :type total_gcount: int
- :param graph_num: Number for this graph, <= total_gcount.
- :type graph_num: int
- :param y_label: Lable of Y axis.
- :type y_label: string
- :param data_col: Data to graph.
- :type data_col: list
-
- """
- # Pagenerics are numrows, numcols, fignum
- pyplot.subplot(total_gcount, 1, graph_num)
- # "go" means green O's
- pyplot.plot(self.run_col, data_col, "go")
- pyplot.xlabel("Run Number")
- pyplot.ylabel(y_label)
-
-
-# Build stats object
-stats = Stats()
-
-# Map of graph names to the Stats.fns that build them
-graph_map = {"min_flows": stats.build_min_flow_graph,
- "max_flows": stats.build_max_flow_graph,
- "flows": stats.build_avg_flow_graph,
- "runtime": stats.build_runtime_graph,
- "iowait": stats.build_iowait_graph,
- "steal_time": stats.build_steal_time_graph,
- "one_load": stats.build_one_load_graph,
- "five_load": stats.build_five_load_graph,
- "fifteen_load": stats.build_fifteen_load_graph,
- "ram": stats.build_ram_graph}
-stats_map = {"min_flows": stats.compute_min_flow_stats,
- "max_flows": stats.compute_max_flow_stats,
- "flows": stats.compute_avg_flow_stats,
- "runtime": stats.compute_runtime_stats,
- "iowait": stats.compute_iowait_stats,
- "steal_time": stats.compute_steal_time_stats,
- "one_load": stats.compute_one_load_stats,
- "five_load": stats.compute_five_load_stats,
- "fifteen_load": stats.compute_fifteen_load_stats,
- "ram": stats.compute_ram_stats}
-
-# Build argument parser
-parser = argparse.ArgumentParser(description="Compute stats about CBench data")
-parser.add_argument("-S", "--all-stats", action="store_true",
- help="compute all stats")
-parser.add_argument("-s", "--stats", choices=stats_map.keys(),
- help="compute stats on specified data", nargs="+")
-parser.add_argument("-G", "--all-graphs", action="store_true",
- help="graph all data")
-parser.add_argument("-g", "--graphs", choices=graph_map.keys(),
- help="graph specified data", nargs="+")
-
-
-# Print help if no arguments are given
-if len(sys.argv) == 1:
- parser.print_help()
- sys.exit(1)
-
-# Parse the given args
-args = parser.parse_args()
-
-# Build graphs
-if args.all_graphs:
- graphs_to_build = graph_map.keys()
-elif args.graphs:
- graphs_to_build = args.graphs
-else:
- graphs_to_build = []
-for graph, graph_num in zip(graphs_to_build, range(len(graphs_to_build))):
- graph_map[graph](len(graphs_to_build), graph_num+1)
-
-# Compute stats
-if args.all_stats:
- stats_to_compute = stats_map.keys()
-elif args.stats:
- stats_to_compute = args.stats
-else:
- stats_to_compute = []
-for stat in stats_to_compute:
- stats_map[stat]()
-
-# Render graphs
-if args.graphs or args.all_graphs:
- # Attempt to adjust plot spacing, just a simple heuristic
- if len(graphs_to_build) <= 3:
- pyplot.subplots_adjust(hspace=.2)
- elif len(graphs_to_build) <= 6:
- pyplot.subplots_adjust(hspace=.4)
- elif len(graphs_to_build) <= 9:
- pyplot.subplots_adjust(hspace=.7)
- else:
- pyplot.subplots_adjust(hspace=.7)
- print "WARNING: That's a lot of graphs. Add a second column?"
- pyplot.show()
-
-# Print stats
-if args.stats or args.all_stats:
- pprint.pprint(stats.results)