blob: 8316b85cb1e194f5ae72b970aaf11c514960d999 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002#
3# Copyright (c) 2011, Intel Corporation.
Patrick Williamsc124f4f2015-09-15 14:41:29 -05004#
Brad Bishopc342db32019-05-15 21:57:59 -04005# SPDX-License-Identifier: GPL-2.0-or-later
Patrick Williamsc124f4f2015-09-15 14:41:29 -05006#
7# Display details of the kernel build size, broken up by built-in.o. Sort
8# the objects by size. Run from the top level kernel build directory.
9#
10# Author: Darren Hart <dvhart@linux.intel.com>
11#
12
13import sys
14import getopt
15import os
16from subprocess import *
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017
18def usage():
19 prog = os.path.basename(sys.argv[0])
Patrick Williamsc0f7c042017-02-23 20:41:17 -060020 print('Usage: %s [OPTION]...' % prog)
21 print(' -d, display an additional level of drivers detail')
22 print(' -h, --help display this help and exit')
23 print('')
24 print('Run %s from the top-level Linux kernel build directory.' % prog)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050025
26
27class Sizes:
28 def __init__(self, glob):
29 self.title = glob
Andrew Geissler82c905d2020-04-13 13:39:40 -050030 p = Popen("size -t " + str(glob), shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031 output = p.communicate()[0].splitlines()
32 if len(output) > 2:
33 sizes = output[-1].split()[0:4]
34 self.text = int(sizes[0])
35 self.data = int(sizes[1])
36 self.bss = int(sizes[2])
37 self.total = int(sizes[3])
38 else:
39 self.text = self.data = self.bss = self.total = 0
40
41 def show(self, indent=""):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060042 print("%-32s %10d | %10d %10d %10d" % \
43 (indent+self.title, self.total, self.text, self.data, self.bss))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044
45
46class Report:
47 def create(filename, title, subglob=None):
48 r = Report(filename, title)
49 path = os.path.dirname(filename)
50
Brad Bishop6e60e8b2018-02-01 10:27:11 -050051 p = Popen("ls " + str(path) + "/*.o | grep -v built-in.o",
Andrew Geissler82c905d2020-04-13 13:39:40 -050052 shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060053 glob = ' '.join(p.communicate()[0].splitlines())
Brad Bishop6e60e8b2018-02-01 10:27:11 -050054 oreport = Report(glob, str(path) + "/*.o")
55 oreport.sizes.title = str(path) + "/*.o"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056 r.parts.append(oreport)
57
58 if subglob:
Andrew Geissler82c905d2020-04-13 13:39:40 -050059 p = Popen("ls " + subglob, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050060 for f in p.communicate()[0].splitlines():
61 path = os.path.dirname(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050062 r.parts.append(Report.create(f, path, str(path) + "/*/built-in.o"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050063 r.parts.sort(reverse=True)
64
65 for b in r.parts:
66 r.totals["total"] += b.sizes.total
67 r.totals["text"] += b.sizes.text
68 r.totals["data"] += b.sizes.data
69 r.totals["bss"] += b.sizes.bss
70
71 r.deltas["total"] = r.sizes.total - r.totals["total"]
72 r.deltas["text"] = r.sizes.text - r.totals["text"]
73 r.deltas["data"] = r.sizes.data - r.totals["data"]
74 r.deltas["bss"] = r.sizes.bss - r.totals["bss"]
75 return r
76 create = staticmethod(create)
77
78 def __init__(self, glob, title):
79 self.glob = glob
80 self.title = title
81 self.sizes = Sizes(glob)
82 self.parts = []
83 self.totals = {"total":0, "text":0, "data":0, "bss":0}
84 self.deltas = {"total":0, "text":0, "data":0, "bss":0}
85
86 def show(self, indent=""):
87 rule = str.ljust(indent, 80, '-')
Patrick Williamsc0f7c042017-02-23 20:41:17 -060088 print("%-32s %10s | %10s %10s %10s" % \
89 (indent+self.title, "total", "text", "data", "bss"))
90 print(rule)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091 self.sizes.show(indent)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060092 print(rule)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093 for p in self.parts:
94 if p.sizes.total > 0:
95 p.sizes.show(indent)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060096 print(rule)
97 print("%-32s %10d | %10d %10d %10d" % \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 (indent+"sum", self.totals["total"], self.totals["text"],
Patrick Williamsc0f7c042017-02-23 20:41:17 -060099 self.totals["data"], self.totals["bss"]))
100 print("%-32s %10d | %10d %10d %10d" % \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 (indent+"delta", self.deltas["total"], self.deltas["text"],
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600102 self.deltas["data"], self.deltas["bss"]))
103 print("\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500105 def __lt__(this, that):
106 if that is None:
107 return 1
108 if not isinstance(that, Report):
109 raise TypeError
110 return this.sizes.total < that.sizes.total
111
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112 def __cmp__(this, that):
113 if that is None:
114 return 1
115 if not isinstance(that, Report):
116 raise TypeError
117 if this.sizes.total < that.sizes.total:
118 return -1
119 if this.sizes.total > that.sizes.total:
120 return 1
121 return 0
122
123
124def main():
125 try:
126 opts, args = getopt.getopt(sys.argv[1:], "dh", ["help"])
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600127 except getopt.GetoptError as err:
128 print('%s' % str(err))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 usage()
130 sys.exit(2)
131
132 driver_detail = False
133 for o, a in opts:
134 if o == '-d':
135 driver_detail = True
136 elif o in ('-h', '--help'):
137 usage()
138 sys.exit(0)
139 else:
140 assert False, "unhandled option"
141
142 glob = "arch/*/built-in.o */built-in.o"
143 vmlinux = Report.create("vmlinux", "Linux Kernel", glob)
144
145 vmlinux.show()
146 for b in vmlinux.parts:
147 if b.totals["total"] > 0 and len(b.parts) > 1:
148 b.show()
149 if b.title == "drivers" and driver_detail:
150 for d in b.parts:
151 if d.totals["total"] > 0 and len(d.parts) > 1:
152 d.show(" ")
153
154
155if __name__ == "__main__":
156 main()