action: footprint tracking
Add action and scripts for footprint tracking. Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
302ac4995b
commit
dfc259d13c
5 changed files with 291 additions and 0 deletions
10
scripts/footprint/plan.txt
Normal file
10
scripts/footprint/plan.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
footprints,default,frdm_k64f,tests/benchmarks/footprints,
|
||||
footprints,userspace,frdm_k64f,tests/benchmarks/footprints,-DCONF_FILE=prj_userspace.conf
|
||||
footprints,default,disco_l475_iot1,tests/benchmarks/footprints,
|
||||
footprints,userspace,disco_l475_iot1,tests/benchmarks/footprints,-DCONF_FILE=prj_userspace.conf
|
||||
footprints,default,nrf5340dk_nrf5340_cpuapp,tests/benchmarks/footprints,
|
||||
footprints,default,nrf51dk_nrf51422,tests/benchmarks/footprints,
|
||||
footprints,default,altera_max10,tests/benchmarks/footprints,
|
||||
footprints,default,hifive1_revb,tests/benchmarks/footprints,
|
||||
footprints,default,ehl_crb,tests/benchmarks/footprints,
|
||||
footprints,userspace,ehl_crb,tests/benchmarks/footprints,-DCONF_FILE=prj_userspace.conf
|
63
scripts/footprint/track.py
Executable file
63
scripts/footprint/track.py
Executable file
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2021 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import csv
|
||||
import subprocess
|
||||
from git import Git
|
||||
import pathlib
|
||||
import shutil
|
||||
import argparse
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate footprint data based on a predefined plan.")
|
||||
parser.add_argument("-p", "--plan", help="Path of test plan", required=True)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
g = Git(".")
|
||||
version = g.describe("--abbrev=12")
|
||||
pathlib.Path(f'footprint_data/{version}').mkdir(exist_ok=True, parents=True)
|
||||
|
||||
with open(args.plan) as csvfile:
|
||||
csvreader = csv.reader(csvfile)
|
||||
for row in csvreader:
|
||||
name=row[0]
|
||||
feature=row[1]
|
||||
board=row[2]
|
||||
app=row[3]
|
||||
options=row[4]
|
||||
|
||||
cmd = ['west',
|
||||
'build',
|
||||
'-d',
|
||||
f'out/{name}/{feature}/{board}',
|
||||
'-b',
|
||||
board,
|
||||
f'{app}',
|
||||
'-t',
|
||||
'footprint']
|
||||
|
||||
if options != '':
|
||||
cmd += ['--', f'{options}']
|
||||
|
||||
print(" ".join(cmd))
|
||||
|
||||
|
||||
try:
|
||||
subprocess.check_output(cmd, stderr=subprocess.STDOUT, timeout=120, universal_newlines=True)
|
||||
print("Copying files...")
|
||||
pathlib.Path(f'footprint_data/{version}/{name}/{feature}/{board}').mkdir(parents=True, exist_ok=True)
|
||||
|
||||
shutil.copy(f'out/{name}/{feature}/{board}/ram.json', f'footprint_data/{version}/{name}/{feature}/{board}')
|
||||
shutil.copy(f'out/{name}/{feature}/{board}/rom.json', f'footprint_data/{version}/{name}/{feature}/{board}')
|
||||
except subprocess.CalledProcessError as exc:
|
||||
print("Status : FAIL", exc.returncode, exc.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
153
scripts/footprint/upload_data.py
Executable file
153
scripts/footprint/upload_data.py
Executable file
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2021 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from anytree.importer import DictImporter
|
||||
from anytree import PreOrderIter
|
||||
from anytree.search import find
|
||||
importer = DictImporter()
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import os
|
||||
import json
|
||||
from git import Repo
|
||||
from git.exc import BadName
|
||||
|
||||
from influxdb import InfluxDBClient
|
||||
import glob
|
||||
import argparse
|
||||
from tabulate import tabulate
|
||||
|
||||
TODAY = datetime.utcnow()
|
||||
two_mon_rel = relativedelta(months=4)
|
||||
|
||||
influx_dsn = 'influxdb://localhost:8086/footprint_tracking'
|
||||
|
||||
def create_event(data, board, feature, commit, current_time, typ, application):
|
||||
footprint_data = []
|
||||
client = InfluxDBClient.from_dsn(influx_dsn)
|
||||
client.create_database('footprint_tracking')
|
||||
for d in data.keys():
|
||||
footprint_data.append({
|
||||
"measurement": d,
|
||||
"tags": {
|
||||
"board": board,
|
||||
"commit": commit,
|
||||
"application": application,
|
||||
"type": typ,
|
||||
"feature": feature
|
||||
},
|
||||
"time": current_time,
|
||||
"fields": {
|
||||
"value": data[d]
|
||||
}
|
||||
})
|
||||
|
||||
client.write_points(footprint_data, time_precision='s', database='footprint_tracking')
|
||||
|
||||
|
||||
def parse_args():
|
||||
global args
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
|
||||
parser.add_argument("-d", "--data", help="Data Directory")
|
||||
parser.add_argument("-y", "--dryrun", action="store_true", help="Dry run, do not upload to database")
|
||||
parser.add_argument("-z", "--zephyr-base", help="Zephyr tree")
|
||||
parser.add_argument("-f", "--file", help="JSON file with footprint data")
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
def parse_file(json_file):
|
||||
|
||||
with open(json_file, "r") as fp:
|
||||
contents = json.load(fp)
|
||||
root = importer.import_(contents['symbols'])
|
||||
|
||||
zr = find(root, lambda node: node.name == 'ZEPHYR_BASE')
|
||||
ws = find(root, lambda node: node.name == 'WORKSPACE')
|
||||
|
||||
data = {}
|
||||
if zr and ws:
|
||||
trees = [zr, ws]
|
||||
else:
|
||||
trees = [root]
|
||||
|
||||
for node in PreOrderIter(root, maxlevel=2):
|
||||
if node.name not in ['WORKSPACE', 'ZEPHYR_BASE']:
|
||||
if node.name in ['Root', 'Symbols']:
|
||||
data['all'] = node.size
|
||||
else:
|
||||
data[node.name] = node.size
|
||||
|
||||
for t in trees:
|
||||
root = t.name
|
||||
for node in PreOrderIter(t, maxlevel=2):
|
||||
if node.name == root:
|
||||
continue
|
||||
comp = node.name
|
||||
if comp in ['Root', 'Symbols']:
|
||||
data['all'] = node.size
|
||||
else:
|
||||
data[comp] = node.size
|
||||
|
||||
return data
|
||||
|
||||
def process_files(data_dir, zephyr_base, dry_run):
|
||||
repo = Repo(zephyr_base)
|
||||
|
||||
for hash in os.listdir(f'{data_dir}'):
|
||||
if not dry_run:
|
||||
client = InfluxDBClient.from_dsn(influx_dsn)
|
||||
result = client.query(f"select * from kernel where commit = '{hash}';")
|
||||
if result:
|
||||
print(f"Skipping {hash}...")
|
||||
continue
|
||||
print(f"Importing {hash}...")
|
||||
for file in glob.glob(f"{args.data}/{hash}/**/*json", recursive=True):
|
||||
file_data = file.split("/")
|
||||
json_file = os.path.basename(file)
|
||||
if 'ram' in json_file:
|
||||
typ = 'ram'
|
||||
else:
|
||||
typ = 'rom'
|
||||
commit = file_data[1]
|
||||
app = file_data[2]
|
||||
feature = file_data[3]
|
||||
board = file_data[4]
|
||||
|
||||
data = parse_file(file)
|
||||
|
||||
try:
|
||||
gitcommit = repo.commit(f'{commit}')
|
||||
current_time = gitcommit.committed_datetime
|
||||
except BadName:
|
||||
cidx = commit.find('-g') + 2
|
||||
gitcommit = repo.commit(f'{commit[cidx:]}')
|
||||
current_time = gitcommit.committed_datetime
|
||||
|
||||
print(current_time)
|
||||
|
||||
if not dry_run:
|
||||
create_event(data, board, feature, commit, current_time, typ, app)
|
||||
|
||||
def main():
|
||||
parse_args()
|
||||
|
||||
if args.data and args.zephyr_base:
|
||||
process_files(args.data, args.zephyr_base, args.dryrun)
|
||||
|
||||
if args.file:
|
||||
data = parse_file(args.file)
|
||||
items = []
|
||||
for component,value in data.items():
|
||||
items.append([component,value])
|
||||
|
||||
table = tabulate(items, headers=['Component', 'Size'], tablefmt='orgtbl')
|
||||
print(table)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue