xref: /openbmc/linux/scripts/bloat-o-meter (revision dec81a532027a77bd52f9bd8d8b3230843533d3f)
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
10d960600dSMatt Mackallimport sys, os, re
11eef06b82SAlexey Dobriyanfrom signal import signal, SIGPIPE, SIG_DFL
12eef06b82SAlexey Dobriyan
13eef06b82SAlexey Dobriyansignal(SIGPIPE, SIG_DFL)
14d960600dSMatt Mackall
15192efb7aSManinder Singhif len(sys.argv) < 3:
16192efb7aSManinder Singh    sys.stderr.write("usage: %s [option] file1 file2\n" % sys.argv[0])
17192efb7aSManinder Singh    sys.stderr.write("The options are:\n")
1861fc4708SMatteo Croce    sys.stderr.write("-c	categorize output based on symbol type\n")
19192efb7aSManinder Singh    sys.stderr.write("-d	Show delta of Data Section\n")
20192efb7aSManinder Singh    sys.stderr.write("-t	Show delta of text Section\n")
21d960600dSMatt Mackall    sys.exit(-1)
22d960600dSMatt Mackall
230d7bbb43SAlexey Dobriyanre_NUMBER = re.compile(r'\.[0-9]+')
240d7bbb43SAlexey Dobriyan
25192efb7aSManinder Singhdef getsizes(file, format):
26d960600dSMatt Mackall    sym = {}
273af06fd9SAlexey Dobriyan    with os.popen("nm --size-sort " + file) as f:
283af06fd9SAlexey Dobriyan        for line in f:
291d35b605SNikolay Borisov            if line.startswith("\n") or ":" in line:
301d35b605SNikolay Borisov                continue
313af06fd9SAlexey Dobriyan            size, type, name = line.split()
32192efb7aSManinder Singh            if type in format:
33c50e3f51SJean Delvare                # strip generated symbols
34c2e182faSJosh Triplett                if name.startswith("__mod_"): continue
35e145242eSDominik Brodowski                if name.startswith("__se_sys"): continue
365ac9efa3SDominik Brodowski                if name.startswith("__se_compat_sys"): continue
37e0b2475aSRasmus Villemoes                if name.startswith("__addressable_"): continue
385a7b2d27SJosh Triplett                if name == "linux_banner": continue
39*dec81a53SPaul Gortmaker                if name == "vermagic": continue
4021cf6e58SAndi Kleen                # statics and some other optimizations adds random .NUMBER
410d7bbb43SAlexey Dobriyan                name = re_NUMBER.sub('', name)
4251849738SRob Landley                sym[name] = sym.get(name, 0) + int(size, 16)
43d960600dSMatt Mackall    return sym
44d960600dSMatt Mackall
45192efb7aSManinder Singhdef calc(oldfile, newfile, format):
46192efb7aSManinder Singh    old = getsizes(oldfile, format)
47192efb7aSManinder Singh    new = getsizes(newfile, format)
48d960600dSMatt Mackall    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
49d960600dSMatt Mackall    delta, common = [], {}
50b21e91c3SVineet Gupta    otot, ntot = 0, 0
51d960600dSMatt Mackall
52d960600dSMatt Mackall    for a in old:
53d960600dSMatt Mackall        if a in new:
54d960600dSMatt Mackall            common[a] = 1
55d960600dSMatt Mackall
56d960600dSMatt Mackall    for name in old:
57b21e91c3SVineet Gupta        otot += old[name]
58d960600dSMatt Mackall        if name not in common:
59d960600dSMatt Mackall            remove += 1
60d960600dSMatt Mackall            down += old[name]
61d960600dSMatt Mackall            delta.append((-old[name], name))
62d960600dSMatt Mackall
63d960600dSMatt Mackall    for name in new:
64b21e91c3SVineet Gupta        ntot += new[name]
65d960600dSMatt Mackall        if name not in common:
66d960600dSMatt Mackall            add += 1
67d960600dSMatt Mackall            up += new[name]
68d960600dSMatt Mackall            delta.append((new[name], name))
69d960600dSMatt Mackall
70d960600dSMatt Mackall    for name in common:
71d960600dSMatt Mackall        d = new.get(name, 0) - old.get(name, 0)
72d960600dSMatt Mackall        if d>0: grow, up = grow+1, up+d
73d960600dSMatt Mackall        if d<0: shrink, down = shrink+1, down-d
74d960600dSMatt Mackall        delta.append((d, name))
75d960600dSMatt Mackall
76d960600dSMatt Mackall    delta.sort()
77d960600dSMatt Mackall    delta.reverse()
78192efb7aSManinder Singh    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
79192efb7aSManinder Singh
80192efb7aSManinder Singhdef print_result(symboltype, symbolformat, argc):
81192efb7aSManinder Singh    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
82192efb7aSManinder Singh    calc(sys.argv[argc - 1], sys.argv[argc], symbolformat)
83d960600dSMatt Mackall
8472214a24SSergey Senozhatsky    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
8572214a24SSergey Senozhatsky          (add, remove, grow, shrink, up, -down, up-down))
86192efb7aSManinder Singh    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
87d960600dSMatt Mackall    for d, n in delta:
8872214a24SSergey Senozhatsky        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
89b21e91c3SVineet Gupta
90edbddb83SAndy Shevchenko    if otot:
91edbddb83SAndy Shevchenko        percent = (ntot - otot) * 100.0 / otot
92edbddb83SAndy Shevchenko    else:
93edbddb83SAndy Shevchenko        percent = 0
94edbddb83SAndy Shevchenko    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
95192efb7aSManinder Singh
96192efb7aSManinder Singhif sys.argv[1] == "-c":
97192efb7aSManinder Singh    print_result("Function", "tT", 3)
98192efb7aSManinder Singh    print_result("Data", "dDbB", 3)
99192efb7aSManinder Singh    print_result("RO Data", "rR", 3)
100192efb7aSManinder Singhelif sys.argv[1] == "-d":
101192efb7aSManinder Singh    print_result("Data", "dDbBrR", 3)
102192efb7aSManinder Singhelif sys.argv[1] == "-t":
103192efb7aSManinder Singh    print_result("Function", "tT", 3)
104192efb7aSManinder Singhelse:
105192efb7aSManinder Singh    print_result("Function", "tTdDbBrR", 2)
106