diff options
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/analysis/cmp-plugins-size.py | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/utils/analysis/cmp-plugins-size.py b/utils/analysis/cmp-plugins-size.py new file mode 100755 index 0000000000..27ffb0fcae --- /dev/null +++ b/utils/analysis/cmp-plugins-size.py | |||
@@ -0,0 +1,159 @@ | |||
1 | #!/usr/bin/python | ||
2 | # -*- coding: utf8 -*- | ||
3 | # __________ __ ___. | ||
4 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | # \/ \/ \/ \/ \/ | ||
9 | # | ||
10 | # Copyright © 2010 Rafaël Carré <rafael.carre@gmail> | ||
11 | # | ||
12 | # This program is free software; you can redistribute it and/or | ||
13 | # modify it under the terms of the GNU General Public License | ||
14 | # as published by the Free Software Foundation; either version 2 | ||
15 | # of the License, or (at your option) any later version. | ||
16 | # | ||
17 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | # KIND, either express or implied. | ||
19 | # | ||
20 | |||
21 | # TODO: iram | ||
22 | |||
23 | import sys | ||
24 | import os | ||
25 | import re | ||
26 | import stat | ||
27 | import fnmatch | ||
28 | |||
29 | |||
30 | def percent_diff(old, new): | ||
31 | if old == 0: | ||
32 | return '?' | ||
33 | diff = 100.0*(new-old)/old | ||
34 | return format(diff, '+2.2f') + '%' | ||
35 | |||
36 | |||
37 | def find_map(dir): | ||
38 | dirs = [] | ||
39 | for file in os.listdir(dir): | ||
40 | path = os.path.join(dir, file) | ||
41 | if stat.S_ISDIR(os.stat(path).st_mode) != 0: | ||
42 | dirs += find_map(path) | ||
43 | elif fnmatch.fnmatch(file, '*.map'): | ||
44 | dirs += [path] | ||
45 | return dirs | ||
46 | |||
47 | |||
48 | def rb_version(dir): | ||
49 | info = os.path.join(dir, 'rockbox-info.txt') | ||
50 | if not os.path.lexists(info): | ||
51 | return 'unknown' | ||
52 | info = open(info).read() | ||
53 | s = re.search('^Version: .*', info, re.MULTILINE) | ||
54 | if not s: | ||
55 | return 'unknown' | ||
56 | return re.sub('^Version: ', '', info[s.start():s.end()]) | ||
57 | |||
58 | |||
59 | def map_info(map): | ||
60 | file = os.path.basename(map) | ||
61 | name = file.rsplit('.map', 1)[0] | ||
62 | |||
63 | # ignore ape-pre map, used to fill IRAM | ||
64 | if name == 'ape-pre': | ||
65 | return None | ||
66 | |||
67 | # ignore overlays | ||
68 | ovlmap = os.path.join(os.path.dirname(map), name, file) | ||
69 | if os.path.lexists(ovlmap): | ||
70 | return None | ||
71 | |||
72 | f = open(map).read() # read map content | ||
73 | |||
74 | s = re.search('^PLUGIN_RAM *0x(\d|[abcdef])*', f, re.MULTILINE) | ||
75 | plugin_start = re.sub('^PLUGIN_RAM *0x0*', '', f[s.start():s.end()]) | ||
76 | |||
77 | s = re.search('^\.pluginend *0x(\d|[abcdef])*', f, re.MULTILINE) | ||
78 | plugin_end = re.sub('^\.pluginend *0x0*', '', f[s.start():s.end()]) | ||
79 | |||
80 | size = int(plugin_end, 16) - int(plugin_start, 16) | ||
81 | return (name, size) | ||
82 | |||
83 | |||
84 | def get_new(oldinfo, newinfo, name): | ||
85 | i = 0 | ||
86 | while i < len(oldinfo) and i < len(newinfo): | ||
87 | if newinfo[i][0] == name: | ||
88 | return newinfo[i] | ||
89 | i += 1 | ||
90 | return None | ||
91 | |||
92 | |||
93 | def compare(olddir, newdir, oldver, newer): | ||
94 | oldinfo = [] | ||
95 | for map in find_map(olddir): | ||
96 | info = map_info(map) | ||
97 | if info: | ||
98 | oldinfo += [info] | ||
99 | |||
100 | newinfo = [] | ||
101 | for map in find_map(newdir): | ||
102 | info = map_info(map) | ||
103 | if info: | ||
104 | newinfo += [info] | ||
105 | |||
106 | oldinfo.sort() | ||
107 | newinfo.sort() | ||
108 | |||
109 | diff = [] | ||
110 | longest_name = 0 | ||
111 | for (name, old_size) in oldinfo: | ||
112 | new = get_new(oldinfo, newinfo, name) | ||
113 | if not new: | ||
114 | continue | ||
115 | (name, new_size) = new | ||
116 | if len(name) > longest_name: | ||
117 | longest_name = len(name) | ||
118 | diff += [(name, new_size - old_size, old_size)] | ||
119 | |||
120 | spacelen = (longest_name + 3) | ||
121 | |||
122 | print(' ' * spacelen + oldver + '\t\t' + newver + '\n') | ||
123 | |||
124 | for (name, diff, old_size) in diff: | ||
125 | space = ' ' * (longest_name - len(name) + 3) | ||
126 | new_size = old_size + diff | ||
127 | pdiff = percent_diff(old_size, new_size) | ||
128 | diff = str(diff) | ||
129 | if diff[0] != '-': | ||
130 | diff = '+' + diff | ||
131 | |||
132 | print(name + space + str(old_size) + '\t' + diff + \ | ||
133 | '\t=\t' + str(new_size) + '\t-->\t' + pdiff) | ||
134 | |||
135 | |||
136 | |||
137 | |||
138 | ### main | ||
139 | |||
140 | |||
141 | if len(sys.argv) != 3: | ||
142 | print('Usage: ' + sys.argv[0] + ' build-old build-new') | ||
143 | sys.exit(1) | ||
144 | |||
145 | oldver = rb_version(sys.argv[1]) | ||
146 | newver = rb_version(sys.argv[2]) | ||
147 | |||
148 | oldplugindir = sys.argv[1] + '/apps/plugins' | ||
149 | newplugindir = sys.argv[2] + '/apps/plugins' | ||
150 | oldcodecsdir = sys.argv[1] + '/apps/codecs' | ||
151 | newcodecsdir = sys.argv[2] + '/apps/codecs' | ||
152 | |||
153 | if os.path.lexists(oldplugindir) and os.path.lexists(newplugindir): | ||
154 | compare(oldplugindir, newplugindir, oldver, newver) | ||
155 | |||
156 | print('\n\n\n') | ||
157 | |||
158 | if os.path.lexists(oldcodecsdir) and os.path.lexists(newcodecsdir): | ||
159 | compare(oldcodecsdir, newcodecsdir, oldver, newver) | ||