xref: /openbmc/linux/scripts/bloat-o-meter (revision 1d35b6054a9b94b48511e23a7fab6cd1dbf3fde6)
1d960600dSMatt Mackall#!/usr/bin/python
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:
29*1d35b605SNikolay Borisov            if line.startswith("\n") or ":" in line:
30*1d35b605SNikolay 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
3921cf6e58SAndi Kleen                # statics and some other optimizations adds random .NUMBER
400d7bbb43SAlexey Dobriyan                name = re_NUMBER.sub('', name)
4151849738SRob Landley                sym[name] = sym.get(name, 0) + int(size, 16)
42d960600dSMatt Mackall    return sym
43d960600dSMatt Mackall
44192efb7aSManinder Singhdef calc(oldfile, newfile, format):
45192efb7aSManinder Singh    old = getsizes(oldfile, format)
46192efb7aSManinder Singh    new = getsizes(newfile, format)
47d960600dSMatt Mackall    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
48d960600dSMatt Mackall    delta, common = [], {}
49b21e91c3SVineet Gupta    otot, ntot = 0, 0
50d960600dSMatt Mackall
51d960600dSMatt Mackall    for a in old:
52d960600dSMatt Mackall        if a in new:
53d960600dSMatt Mackall            common[a] = 1
54d960600dSMatt Mackall
55d960600dSMatt Mackall    for name in old:
56b21e91c3SVineet Gupta        otot += old[name]
57d960600dSMatt Mackall        if name not in common:
58d960600dSMatt Mackall            remove += 1
59d960600dSMatt Mackall            down += old[name]
60d960600dSMatt Mackall            delta.append((-old[name], name))
61d960600dSMatt Mackall
62d960600dSMatt Mackall    for name in new:
63b21e91c3SVineet Gupta        ntot += new[name]
64d960600dSMatt Mackall        if name not in common:
65d960600dSMatt Mackall            add += 1
66d960600dSMatt Mackall            up += new[name]
67d960600dSMatt Mackall            delta.append((new[name], name))
68d960600dSMatt Mackall
69d960600dSMatt Mackall    for name in common:
70d960600dSMatt Mackall        d = new.get(name, 0) - old.get(name, 0)
71d960600dSMatt Mackall        if d>0: grow, up = grow+1, up+d
72d960600dSMatt Mackall        if d<0: shrink, down = shrink+1, down-d
73d960600dSMatt Mackall        delta.append((d, name))
74d960600dSMatt Mackall
75d960600dSMatt Mackall    delta.sort()
76d960600dSMatt Mackall    delta.reverse()
77192efb7aSManinder Singh    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
78192efb7aSManinder Singh
79192efb7aSManinder Singhdef print_result(symboltype, symbolformat, argc):
80192efb7aSManinder Singh    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
81192efb7aSManinder Singh    calc(sys.argv[argc - 1], sys.argv[argc], symbolformat)
82d960600dSMatt Mackall
8372214a24SSergey Senozhatsky    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
8472214a24SSergey Senozhatsky          (add, remove, grow, shrink, up, -down, up-down))
85192efb7aSManinder Singh    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
86d960600dSMatt Mackall    for d, n in delta:
8772214a24SSergey Senozhatsky        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
88b21e91c3SVineet Gupta
89edbddb83SAndy Shevchenko    if otot:
90edbddb83SAndy Shevchenko        percent = (ntot - otot) * 100.0 / otot
91edbddb83SAndy Shevchenko    else:
92edbddb83SAndy Shevchenko        percent = 0
93edbddb83SAndy Shevchenko    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
94192efb7aSManinder Singh
95192efb7aSManinder Singhif sys.argv[1] == "-c":
96192efb7aSManinder Singh    print_result("Function", "tT", 3)
97192efb7aSManinder Singh    print_result("Data", "dDbB", 3)
98192efb7aSManinder Singh    print_result("RO Data", "rR", 3)
99192efb7aSManinder Singhelif sys.argv[1] == "-d":
100192efb7aSManinder Singh    print_result("Data", "dDbBrR", 3)
101192efb7aSManinder Singhelif sys.argv[1] == "-t":
102192efb7aSManinder Singh    print_result("Function", "tT", 3)
103192efb7aSManinder Singhelse:
104192efb7aSManinder Singh    print_result("Function", "tTdDbBrR", 2)
105