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