CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/scripts/build_tests/pretty_diff_size.py
Views: 1799
1
#!/usr/bin/env python
2
3
'''
4
This script intend to provide a pretty size diff between two binaries.
5
6
AP_FLAKE8_CLEAN
7
'''
8
9
import os
10
from argparse import ArgumentParser
11
from tabulate import tabulate
12
13
parser = ArgumentParser(description="Print binary size difference with master.")
14
parser.add_argument("-m", "--master", dest='master', type=str, help="Master Binaries Path", required=True)
15
parser.add_argument("-s", "--second", dest='second', type=str, help="Second Binaries Path", required=True)
16
17
args = parser.parse_args()
18
19
20
def sizes_for_file(filepath):
21
"""Get binary size information with size."""
22
print("Get binary size of %s" % filepath)
23
cmd = "size %s" % (filepath,)
24
stuff = os.popen(cmd).read()
25
lines = stuff.splitlines()[1:]
26
size_list = []
27
for line in lines:
28
row = line.strip().split()
29
size_list.append(dict(
30
text=int(row[0]),
31
data=int(row[1]),
32
bss=int(row[2]),
33
total=int(row[3]),
34
))
35
36
# Get the size of .crash_log to remove it from .bss reporting
37
cmd = "size -A %s" % (filepath,)
38
output = os.popen(cmd).read()
39
lines = output.splitlines()[1:]
40
for line in lines:
41
if ".crash_log" in line:
42
row = line.strip().split()
43
size_list[0]["crash_log"] = int(row[1])
44
break
45
46
# check if crash_log wasn't found and set to 0B if not found
47
# FIX ME : so it doesn't report Flash_Free 0B for non-ARM boards
48
if size_list[0].get("crash_log") is None:
49
size_list[0]["crash_log"] = 0
50
51
return size_list
52
53
54
def print_table(summary_data_list_second, summary_data_list_master):
55
"""Print the binaries size diff on a table."""
56
print_data = []
57
print("")
58
# print(summary_data_list_second)
59
# print(summary_data_list_master)
60
for name in summary_data_list_second[0]:
61
for master_name in summary_data_list_master[0]:
62
if name == master_name:
63
col_data = [name]
64
for key in ["text", "data", "bss", "total"]:
65
bvalue = summary_data_list_second[0][name].get(key)
66
mvalue = summary_data_list_master[0][name].get(key)
67
68
# BSS: remove the portion occupied by crash_log as the command `size binary.elf`
69
# reports BSS with crash_log included
70
if key == "bss":
71
mvalue = (summary_data_list_master[0][name].get("bss") -
72
summary_data_list_master[0][name].get("crash_log"))
73
bvalue = (summary_data_list_second[0][name].get("bss") -
74
summary_data_list_second[0][name].get("crash_log"))
75
76
# Total Flash Cost = Data + Text
77
if key == "total":
78
mvalue = (summary_data_list_master[0][name].get("text") +
79
summary_data_list_master[0][name].get("data"))
80
bvalue = (summary_data_list_second[0][name].get("text") +
81
summary_data_list_second[0][name].get("data"))
82
diff = (bvalue - mvalue) * 100.0 / mvalue
83
signum = "+" if diff > 0.0 else ""
84
print_diff = str(bvalue - mvalue)
85
print_diff += " (" + signum + "%0.4f%%" % diff + ")"
86
col_data.append(print_diff)
87
88
# Append free flash space which is equivalent to crash_log's size
89
col_data.append(str(summary_data_list_second[0][name].get("crash_log")))
90
print_data.append(col_data)
91
print(tabulate(print_data, headers=["Binary Name", "Text [B]", "Data [B]", "BSS (B)",
92
"Total Flash Change [B] (%)", "Flash Free After PR (B)"]))
93
# Get the GitHub Actions summary file path
94
summary_file = os.getenv('GITHUB_STEP_SUMMARY')
95
if summary_file:
96
# Append the output to the summary file
97
with open(summary_file, 'a') as f:
98
f.write("### Diff summary\n")
99
f.write(tabulate(print_data, headers=[
100
"Binary Name",
101
"Text [B]",
102
"Data [B]",
103
"BSS (B)",
104
"Total Flash Change [B] (%)",
105
"Flash Free After PR (B)"
106
], tablefmt="github"))
107
f.write("\n")
108
109
110
def extract_binaries_size(path):
111
"""Search and extract binary size for each binary in the given path."""
112
print("Extracting binaries size on %s" % path)
113
binaries_list = []
114
for file in os.listdir(args.master):
115
fileNoExt = os.path.splitext(file)[0]
116
binaries_list.append(fileNoExt)
117
binaries_list = list(dict.fromkeys(binaries_list))
118
if len(binaries_list) == 0:
119
print("Failed to get binaries")
120
121
size_dict = None
122
for binaries in binaries_list:
123
binary_path = os.path.join(path, binaries)
124
parsed = sizes_for_file(binary_path)
125
if size_dict is None:
126
size_dict = [{binaries.lower(): parsed[0]}]
127
else:
128
size_dict[0].update({binaries.lower(): parsed[0]})
129
print("Success !")
130
return size_dict
131
132
133
master_dict = extract_binaries_size(args.master)
134
second_dict = extract_binaries_size(args.second)
135
136
print_table(second_dict, master_dict)
137
138