123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import sys
- import argparse
- import sqlite3
- import matplotlib.pyplot as plt
- import numpy as np
- # usage: single db file
- # python3 rolling.py plot DB_FILE_PATH [--perf-name PERF_NAME] [--aggregate AGGREGATE] [--interval INTERVAL] [--perf-file PERF_FILE]
- #
- # usage: diff mutiple db files
- # python3 rolling.py diff MUTI_DB_FILE_PATH [--perf-name PERF_NAME] [--aggregate AGGREGATE] [--interval INTERVAL] [--perf-file PERF_FILE]
- #
- # If you only observe one rolling counter, indicate the --perf-name parameter.
- # If you want to observe multiple at the same time, you can indicate the --perf-file parameter,
- # pointing to the path to a description file, each line in the file is a rolling counter,
- # and you can use the '//' comment at the beginning of the line to remove the unconcerned counter.
- #
- # Note that generally speaking, when observing multiple rolling counters,
- # the meaning of the x-axis needs to be the same, then you can use the intervalBased mode.
- #
- # If you want to compare multiple dbs to observe the difference between multiple runs, you can use diff mode.
- # This requires specifying the path of a description file. Each line in this description file contains a specific db path.
- #
- # eg.
- # exec emu twice with different parameters and obtained different db files (db0, db1).
- # want to observe the changes in IPC and prefetch accuracy.
- # create a file named db.txt:
- # path to db0
- # path to db1
- # create a file named perf.txt:
- # IPC
- # L1PrefetchAccuracy
- # run `python3 rolling.py diff db.txt --perf-file perf.txt -I (interval in RTL)`
- # eg.
- # want to observe the IPC rolling in single db (db0).
- # run `python3 rolling.py plot path-to-db0 --perf-name IPC`
- #
- class DataSet:
-
- def __init__(self, db_path):
- self.conn = sqlite3.connect(db_path)
- self.cursor = self.conn.cursor()
- self.xdata = []
- self.ydata = []
-
- def derive(self, perf_name, aggregate, clk_itval, hart):
- sql = "SELECT xAxisPt, yAxisPt FROM {}_rolling_{}".format(perf_name, hart)
- self.cursor.execute(sql)
- result = self.cursor.fetchall()
- aggcnt = 0
- recordcnt = 0
- aggydata = 0
- aggxdata = 0
- self.xdata = []
- self.ydata = []
- if clk_itval == -1:
- # normal mode
- # db log in normal mode: (xAxis, ydata)
- # xAxis is current position in X Axis, ydata is the Increment value between this point and last point
- for row in result:
- aggcnt += 1
- aggydata += row[1]
- if aggcnt == aggregate:
- self.xdata.append(row[0])
- self.ydata.append(aggydata/(row[0]-aggxdata))
- aggcnt = 0
- aggydata = 0
- aggxdata = row[0]
- else:
- # intervalBased mode, -I interval should be specified
- # db log in intervalBased mode: (xdata, ydata)
- # xdata, ydata in the Increment value in a certain interval
- for row in result:
- aggcnt += 1
- aggxdata += row[0]
- aggydata += row[1]
- if aggcnt == aggregate:
- self.xdata.append((clk_itval * aggregate) * (recordcnt + 1))
- self.ydata.append(0 if aggydata == 0 else aggxdata/aggydata)
- aggcnt = 0
- aggxdata = 0
- aggydata = 0
- recordcnt += 1
-
- def plot(self, lb='PERF'):
- plt.plot(self.xdata, self.ydata, lw=1, ls='-', label=lb)
-
- def legend():
- plt.legend()
-
- def show():
- plt.show()
- def err_exit(msg):
- print(msg)
- sys.exit(1)
- def check_args(args):
- if args.aggregate <= 0:
- err_exit("aggregation ratio must be no less than 1")
- if not args.perf_name and not args.perf_file:
- err_exit("should either specify perf-name or perf-file")
- def plot_dataset(path, perf_name, aggregate, clk_itval, perf_file, db_id=-1):
- dataset = DataSet(path)
- label = '_' + str(db_id) if db_id != -1 else ''
-
- if perf_file:
- with open(perf_file) as fp:
- perfs = fp.readlines()
- perfs = [perf.strip() for perf in perfs]
- perfs = list(filter(lambda x: not x.startswith('//'), perfs))
- for perf in perfs:
- dataset.derive(perf, aggregate, clk_itval, 0)
- dataset.plot(perf + label)
- else:
- dataset.derive(perf_name, aggregate, clk_itval, 0)
- dataset.plot(perf_name + label)
- def handle_plot(args):
- check_args(args)
-
- plot_dataset(args.db_path, args.perf_name, args.aggregate, args.interval, args.perf_file)
-
- DataSet.legend()
- DataSet.show()
- def handle_diff(args):
- check_args(args)
-
- db_path = args.db_path
-
- with open(db_path) as fp:
- for (idx, db) in enumerate(fp):
- plot_dataset(db.strip(), args.perf_name, args.aggregate, args.interval, args.perf_file, idx)
-
- DataSet.legend()
- DataSet.show()
- if __name__ == "__main__":
- parser = argparse.ArgumentParser(description="performance rolling plot script for xs")
- subparsers = parser.add_subparsers(title='useful sub function', dest='subcommand', help='useful sub function')
-
- # sub function for single db file
- cmd1_parser = subparsers.add_parser('plot', help='for single db file')
- cmd1_parser.add_argument('db_path', metavar='db_path', type=str, help='path to chiseldb file')
- cmd1_parser.add_argument('--perf-name', default=None, type=str, help="name of the performance counter")
- cmd1_parser.add_argument('--aggregate', '-A', default=1, type=int, help="aggregation ratio")
- cmd1_parser.add_argument('--interval', '-I', default=-1, type=int, help="interval value in the interval based mode")
- cmd1_parser.add_argument('--perf-file', '-F', default=None, type=str, help="path to a file including all interested performance counters")
-
- # sub function for diff multiple db files
- cmd2_parser = subparsers.add_parser('diff', help='for diff multiple db files')
- cmd2_parser.add_argument('db_path', metavar='muti_db_path', type=str, help="path to a file including all path to chiseldb files")
- cmd2_parser.add_argument('--perf-name', default=None, type=str, help="name of the performance counter")
- cmd2_parser.add_argument('--aggregate', '-A', default=1, type=int, help="aggregation ratio")
- cmd2_parser.add_argument('--interval', '-I', default=-1, type=int, help="interval value in the interval based mode")
- cmd2_parser.add_argument('--perf-file', '-F', default=None, type=str, help="path to a file including all interested performance counters")
- args = parser.parse_args()
-
- if args.subcommand == 'plot':
- handle_plot(args)
- elif args.subcommand == 'diff':
- handle_diff(args)
- else:
- err_exit('invalid command')
|