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