xref: /openbmc/linux/scripts/bloat-o-meter (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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(reverse=True)
84d960600dSMatt Mackall    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
85192efb7aSManinder Singh
86192efb7aSManinder Singhdef print_result(symboltype, symbolformat):
87b62eb273SNikolay Borisov    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
88192efb7aSManinder Singh    calc(args.file1, args.file2, symbolformat)
89b62eb273SNikolay Borisov
90d960600dSMatt Mackall    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
9172214a24SSergey Senozhatsky          (add, remove, grow, shrink, up, -down, up-down))
9272214a24SSergey Senozhatsky    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
93192efb7aSManinder Singh    for d, n in delta:
94d960600dSMatt Mackall        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
9572214a24SSergey Senozhatsky
96b21e91c3SVineet Gupta    if otot:
97edbddb83SAndy Shevchenko        percent = (ntot - otot) * 100.0 / otot
98edbddb83SAndy Shevchenko    else:
99edbddb83SAndy Shevchenko        percent = 0
100edbddb83SAndy Shevchenko    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
101edbddb83SAndy Shevchenko
102192efb7aSManinder Singhif args.c:
103b62eb273SNikolay Borisov    print_result("Function", "tTwW")
104b62eb273SNikolay Borisov    print_result("Data", "dDbBvV")
105b62eb273SNikolay Borisov    print_result("RO Data", "rR")
106b62eb273SNikolay Borisovelif args.d:
107b62eb273SNikolay Borisov    print_result("Data", "dDbBrRvV")
108b62eb273SNikolay Borisovelif args.t:
109b62eb273SNikolay Borisov    print_result("Function", "tTwW")
110b62eb273SNikolay Borisovelse:
111192efb7aSManinder Singh    print_result("Function", "tTdDbBrRvVwW")
112b62eb273SNikolay Borisov