xref: /openbmc/linux/scripts/bloat-o-meter (revision 8b5db6679807fd0ab1154375ea6e5aa6b11c4350)
151839e29SAndy Shevchenko#!/usr/bin/env python3
2d960600dSMatt Mackall#
3d960600dSMatt Mackall# Copyright 2004 Matt Mackall <mpm@selenic.com>
4d960600dSMatt Mackall#
5d960600dSMatt Mackall# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
6d960600dSMatt Mackall#
7d960600dSMatt Mackall# This software may be used and distributed according to the terms
8d960600dSMatt Mackall# of the GNU General Public License, incorporated herein by reference.
9d960600dSMatt Mackall
10b62eb273SNikolay Borisovimport sys, os, re, argparse
11eef06b82SAlexey Dobriyanfrom signal import signal, SIGPIPE, SIG_DFL
12eef06b82SAlexey Dobriyan
13eef06b82SAlexey Dobriyansignal(SIGPIPE, SIG_DFL)
14d960600dSMatt Mackall
15b62eb273SNikolay Borisovparser = argparse.ArgumentParser(description="Simple script used to compare the symbol sizes of 2 object files")
16b62eb273SNikolay Borisovgroup = parser.add_mutually_exclusive_group()
17b62eb273SNikolay Borisovgroup.add_argument('-c', help='categorize output based on symbol type', action='store_true')
18b62eb273SNikolay Borisovgroup.add_argument('-d', help='Show delta of Data Section', action='store_true')
19b62eb273SNikolay Borisovgroup.add_argument('-t', help='Show delta of text Section', action='store_true')
20*8b5db667SNikolay Borisovparser.add_argument('-p', dest='prefix', help='Arch prefix for the tool being used. Useful in cross build scenarios')
21b62eb273SNikolay Borisovparser.add_argument('file1', help='First file to compare')
22b62eb273SNikolay Borisovparser.add_argument('file2', help='Second file to compare')
23b62eb273SNikolay Borisov
24b62eb273SNikolay Borisovargs = parser.parse_args()
25d960600dSMatt Mackall
260d7bbb43SAlexey Dobriyanre_NUMBER = re.compile(r'\.[0-9]+')
270d7bbb43SAlexey Dobriyan
28192efb7aSManinder Singhdef getsizes(file, format):
29d960600dSMatt Mackall    sym = {}
30*8b5db667SNikolay Borisov    nm = "nm"
31*8b5db667SNikolay Borisov    if args.prefix:
32*8b5db667SNikolay Borisov        nm = "{}nm".format(args.prefix)
33*8b5db667SNikolay Borisov
34*8b5db667SNikolay Borisov    with os.popen("{} --size-sort {}".format(nm, file)) as f:
353af06fd9SAlexey Dobriyan        for line in f:
361d35b605SNikolay Borisov            if line.startswith("\n") or ":" in line:
371d35b605SNikolay Borisov                continue
383af06fd9SAlexey Dobriyan            size, type, name = line.split()
39192efb7aSManinder Singh            if type in format:
40c50e3f51SJean Delvare                # strip generated symbols
41c2e182faSJosh Triplett                if name.startswith("__mod_"): continue
42e145242eSDominik Brodowski                if name.startswith("__se_sys"): continue
435ac9efa3SDominik Brodowski                if name.startswith("__se_compat_sys"): continue
44e0b2475aSRasmus Villemoes                if name.startswith("__addressable_"): continue
455a7b2d27SJosh Triplett                if name == "linux_banner": continue
46dec81a53SPaul Gortmaker                if name == "vermagic": continue
4721cf6e58SAndi Kleen                # statics and some other optimizations adds random .NUMBER
480d7bbb43SAlexey Dobriyan                name = re_NUMBER.sub('', name)
4951849738SRob Landley                sym[name] = sym.get(name, 0) + int(size, 16)
50d960600dSMatt Mackall    return sym
51d960600dSMatt Mackall
52192efb7aSManinder Singhdef calc(oldfile, newfile, format):
53192efb7aSManinder Singh    old = getsizes(oldfile, format)
54192efb7aSManinder Singh    new = getsizes(newfile, format)
55d960600dSMatt Mackall    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
56d960600dSMatt Mackall    delta, common = [], {}
57b21e91c3SVineet Gupta    otot, ntot = 0, 0
58d960600dSMatt Mackall
59d960600dSMatt Mackall    for a in old:
60d960600dSMatt Mackall        if a in new:
61d960600dSMatt Mackall            common[a] = 1
62d960600dSMatt Mackall
63d960600dSMatt Mackall    for name in old:
64b21e91c3SVineet Gupta        otot += old[name]
65d960600dSMatt Mackall        if name not in common:
66d960600dSMatt Mackall            remove += 1
67d960600dSMatt Mackall            down += old[name]
68d960600dSMatt Mackall            delta.append((-old[name], name))
69d960600dSMatt Mackall
70d960600dSMatt Mackall    for name in new:
71b21e91c3SVineet Gupta        ntot += new[name]
72d960600dSMatt Mackall        if name not in common:
73d960600dSMatt Mackall            add += 1
74d960600dSMatt Mackall            up += new[name]
75d960600dSMatt Mackall            delta.append((new[name], name))
76d960600dSMatt Mackall
77d960600dSMatt Mackall    for name in common:
78d960600dSMatt Mackall        d = new.get(name, 0) - old.get(name, 0)
79d960600dSMatt Mackall        if d>0: grow, up = grow+1, up+d
80d960600dSMatt Mackall        if d<0: shrink, down = shrink+1, down-d
81d960600dSMatt Mackall        delta.append((d, name))
82d960600dSMatt Mackall
83d960600dSMatt Mackall    delta.sort()
84d960600dSMatt Mackall    delta.reverse()
85192efb7aSManinder Singh    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
86192efb7aSManinder Singh
87b62eb273SNikolay Borisovdef print_result(symboltype, symbolformat):
88192efb7aSManinder Singh    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
89b62eb273SNikolay Borisov    calc(args.file1, args.file2, symbolformat)
90d960600dSMatt Mackall
9172214a24SSergey Senozhatsky    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
9272214a24SSergey Senozhatsky          (add, remove, grow, shrink, up, -down, up-down))
93192efb7aSManinder Singh    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
94d960600dSMatt Mackall    for d, n in delta:
9572214a24SSergey Senozhatsky        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
96b21e91c3SVineet Gupta
97edbddb83SAndy Shevchenko    if otot:
98edbddb83SAndy Shevchenko        percent = (ntot - otot) * 100.0 / otot
99edbddb83SAndy Shevchenko    else:
100edbddb83SAndy Shevchenko        percent = 0
101edbddb83SAndy Shevchenko    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
102192efb7aSManinder Singh
103b62eb273SNikolay Borisovif args.c:
104b62eb273SNikolay Borisov    print_result("Function", "tT")
105b62eb273SNikolay Borisov    print_result("Data", "dDbB")
106b62eb273SNikolay Borisov    print_result("RO Data", "rR")
107b62eb273SNikolay Borisovelif args.d:
108b62eb273SNikolay Borisov    print_result("Data", "dDbBrR")
109b62eb273SNikolay Borisovelif args.t:
110b62eb273SNikolay Borisov    print_result("Function", "tT")
111192efb7aSManinder Singhelse:
112b62eb273SNikolay Borisov    print_result("Function", "tTdDbBrR")
113