xref: /openbmc/linux/scripts/bloat-o-meter (revision e0b2475a3f36a7a0a001fe552145055da1daf245)
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:
293af06fd9SAlexey Dobriyan            size, type, name = line.split()
30192efb7aSManinder Singh            if type in format:
31c50e3f51SJean Delvare                # strip generated symbols
32c2e182faSJosh Triplett                if name.startswith("__mod_"): continue
33e145242eSDominik Brodowski                if name.startswith("__se_sys"): continue
345ac9efa3SDominik Brodowski                if name.startswith("__se_compat_sys"): continue
35*e0b2475aSRasmus Villemoes                if name.startswith("__addressable_"): continue
365a7b2d27SJosh Triplett                if name == "linux_banner": continue
3721cf6e58SAndi Kleen                # statics and some other optimizations adds random .NUMBER
380d7bbb43SAlexey Dobriyan                name = re_NUMBER.sub('', name)
3951849738SRob Landley                sym[name] = sym.get(name, 0) + int(size, 16)
40d960600dSMatt Mackall    return sym
41d960600dSMatt Mackall
42192efb7aSManinder Singhdef calc(oldfile, newfile, format):
43192efb7aSManinder Singh    old = getsizes(oldfile, format)
44192efb7aSManinder Singh    new = getsizes(newfile, format)
45d960600dSMatt Mackall    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
46d960600dSMatt Mackall    delta, common = [], {}
47b21e91c3SVineet Gupta    otot, ntot = 0, 0
48d960600dSMatt Mackall
49d960600dSMatt Mackall    for a in old:
50d960600dSMatt Mackall        if a in new:
51d960600dSMatt Mackall            common[a] = 1
52d960600dSMatt Mackall
53d960600dSMatt Mackall    for name in old:
54b21e91c3SVineet Gupta        otot += old[name]
55d960600dSMatt Mackall        if name not in common:
56d960600dSMatt Mackall            remove += 1
57d960600dSMatt Mackall            down += old[name]
58d960600dSMatt Mackall            delta.append((-old[name], name))
59d960600dSMatt Mackall
60d960600dSMatt Mackall    for name in new:
61b21e91c3SVineet Gupta        ntot += new[name]
62d960600dSMatt Mackall        if name not in common:
63d960600dSMatt Mackall            add += 1
64d960600dSMatt Mackall            up += new[name]
65d960600dSMatt Mackall            delta.append((new[name], name))
66d960600dSMatt Mackall
67d960600dSMatt Mackall    for name in common:
68d960600dSMatt Mackall        d = new.get(name, 0) - old.get(name, 0)
69d960600dSMatt Mackall        if d>0: grow, up = grow+1, up+d
70d960600dSMatt Mackall        if d<0: shrink, down = shrink+1, down-d
71d960600dSMatt Mackall        delta.append((d, name))
72d960600dSMatt Mackall
73d960600dSMatt Mackall    delta.sort()
74d960600dSMatt Mackall    delta.reverse()
75192efb7aSManinder Singh    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
76192efb7aSManinder Singh
77192efb7aSManinder Singhdef print_result(symboltype, symbolformat, argc):
78192efb7aSManinder Singh    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
79192efb7aSManinder Singh    calc(sys.argv[argc - 1], sys.argv[argc], symbolformat)
80d960600dSMatt Mackall
8172214a24SSergey Senozhatsky    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
8272214a24SSergey Senozhatsky          (add, remove, grow, shrink, up, -down, up-down))
83192efb7aSManinder Singh    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
84d960600dSMatt Mackall    for d, n in delta:
8572214a24SSergey Senozhatsky        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
86b21e91c3SVineet Gupta
87edbddb83SAndy Shevchenko    if otot:
88edbddb83SAndy Shevchenko        percent = (ntot - otot) * 100.0 / otot
89edbddb83SAndy Shevchenko    else:
90edbddb83SAndy Shevchenko        percent = 0
91edbddb83SAndy Shevchenko    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
92192efb7aSManinder Singh
93192efb7aSManinder Singhif sys.argv[1] == "-c":
94192efb7aSManinder Singh    print_result("Function", "tT", 3)
95192efb7aSManinder Singh    print_result("Data", "dDbB", 3)
96192efb7aSManinder Singh    print_result("RO Data", "rR", 3)
97192efb7aSManinder Singhelif sys.argv[1] == "-d":
98192efb7aSManinder Singh    print_result("Data", "dDbBrR", 3)
99192efb7aSManinder Singhelif sys.argv[1] == "-t":
100192efb7aSManinder Singh    print_result("Function", "tT", 3)
101192efb7aSManinder Singhelse:
102192efb7aSManinder Singh    print_result("Function", "tTdDbBrR", 2)
103