xref: /OK3568_Linux_fs/kernel/scripts/bloat-o-meter (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env python3
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# Copyright 2004 Matt Mackall <mpm@selenic.com>
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun# This software may be used and distributed according to the terms
8*4882a593Smuzhiyun# of the GNU General Public License, incorporated herein by reference.
9*4882a593Smuzhiyun
10*4882a593Smuzhiyunimport sys, os, re
11*4882a593Smuzhiyunfrom signal import signal, SIGPIPE, SIG_DFL
12*4882a593Smuzhiyun
13*4882a593Smuzhiyunsignal(SIGPIPE, SIG_DFL)
14*4882a593Smuzhiyun
15*4882a593Smuzhiyunif len(sys.argv) < 3:
16*4882a593Smuzhiyun    sys.stderr.write("usage: %s [option] file1 file2\n" % sys.argv[0])
17*4882a593Smuzhiyun    sys.stderr.write("The options are:\n")
18*4882a593Smuzhiyun    sys.stderr.write("-c	categorize output based on symbol type\n")
19*4882a593Smuzhiyun    sys.stderr.write("-d	Show delta of Data Section\n")
20*4882a593Smuzhiyun    sys.stderr.write("-t	Show delta of text Section\n")
21*4882a593Smuzhiyun    sys.exit(-1)
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunre_NUMBER = re.compile(r'\.[0-9]+')
24*4882a593Smuzhiyun
25*4882a593Smuzhiyundef getsizes(file, format):
26*4882a593Smuzhiyun    sym = {}
27*4882a593Smuzhiyun    with os.popen("nm --size-sort " + file) as f:
28*4882a593Smuzhiyun        for line in f:
29*4882a593Smuzhiyun            if line.startswith("\n") or ":" in line:
30*4882a593Smuzhiyun                continue
31*4882a593Smuzhiyun            size, type, name = line.split()
32*4882a593Smuzhiyun            if type in format:
33*4882a593Smuzhiyun                # strip generated symbols
34*4882a593Smuzhiyun                if name.startswith("__mod_"): continue
35*4882a593Smuzhiyun                if name.startswith("__se_sys"): continue
36*4882a593Smuzhiyun                if name.startswith("__se_compat_sys"): continue
37*4882a593Smuzhiyun                if name.startswith("__addressable_"): continue
38*4882a593Smuzhiyun                if name == "linux_banner": continue
39*4882a593Smuzhiyun                # statics and some other optimizations adds random .NUMBER
40*4882a593Smuzhiyun                name = re_NUMBER.sub('', name)
41*4882a593Smuzhiyun                sym[name] = sym.get(name, 0) + int(size, 16)
42*4882a593Smuzhiyun    return sym
43*4882a593Smuzhiyun
44*4882a593Smuzhiyundef calc(oldfile, newfile, format):
45*4882a593Smuzhiyun    old = getsizes(oldfile, format)
46*4882a593Smuzhiyun    new = getsizes(newfile, format)
47*4882a593Smuzhiyun    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
48*4882a593Smuzhiyun    delta, common = [], {}
49*4882a593Smuzhiyun    otot, ntot = 0, 0
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun    for a in old:
52*4882a593Smuzhiyun        if a in new:
53*4882a593Smuzhiyun            common[a] = 1
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun    for name in old:
56*4882a593Smuzhiyun        otot += old[name]
57*4882a593Smuzhiyun        if name not in common:
58*4882a593Smuzhiyun            remove += 1
59*4882a593Smuzhiyun            down += old[name]
60*4882a593Smuzhiyun            delta.append((-old[name], name))
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun    for name in new:
63*4882a593Smuzhiyun        ntot += new[name]
64*4882a593Smuzhiyun        if name not in common:
65*4882a593Smuzhiyun            add += 1
66*4882a593Smuzhiyun            up += new[name]
67*4882a593Smuzhiyun            delta.append((new[name], name))
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun    for name in common:
70*4882a593Smuzhiyun        d = new.get(name, 0) - old.get(name, 0)
71*4882a593Smuzhiyun        if d>0: grow, up = grow+1, up+d
72*4882a593Smuzhiyun        if d<0: shrink, down = shrink+1, down-d
73*4882a593Smuzhiyun        delta.append((d, name))
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun    delta.sort()
76*4882a593Smuzhiyun    delta.reverse()
77*4882a593Smuzhiyun    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
78*4882a593Smuzhiyun
79*4882a593Smuzhiyundef print_result(symboltype, symbolformat, argc):
80*4882a593Smuzhiyun    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
81*4882a593Smuzhiyun    calc(sys.argv[argc - 1], sys.argv[argc], symbolformat)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
84*4882a593Smuzhiyun          (add, remove, grow, shrink, up, -down, up-down))
85*4882a593Smuzhiyun    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
86*4882a593Smuzhiyun    for d, n in delta:
87*4882a593Smuzhiyun        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun    if otot:
90*4882a593Smuzhiyun        percent = (ntot - otot) * 100.0 / otot
91*4882a593Smuzhiyun    else:
92*4882a593Smuzhiyun        percent = 0
93*4882a593Smuzhiyun    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
94*4882a593Smuzhiyun
95*4882a593Smuzhiyunif sys.argv[1] == "-c":
96*4882a593Smuzhiyun    print_result("Function", "tT", 3)
97*4882a593Smuzhiyun    print_result("Data", "dDbB", 3)
98*4882a593Smuzhiyun    print_result("RO Data", "rR", 3)
99*4882a593Smuzhiyunelif sys.argv[1] == "-d":
100*4882a593Smuzhiyun    print_result("Data", "dDbBrR", 3)
101*4882a593Smuzhiyunelif sys.argv[1] == "-t":
102*4882a593Smuzhiyun    print_result("Function", "tT", 3)
103*4882a593Smuzhiyunelse:
104*4882a593Smuzhiyun    print_result("Function", "tTdDbBrR", 2)
105