ksize.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/env python3
  2. #
  3. # Copyright (c) 2011, Intel Corporation.
  4. # All rights reserved.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. #
  20. #
  21. # Display details of the kernel build size, broken up by built-in.o. Sort
  22. # the objects by size. Run from the top level kernel build directory.
  23. #
  24. # Author: Darren Hart <dvhart@linux.intel.com>
  25. #
  26. import sys
  27. import getopt
  28. import os
  29. from subprocess import *
  30. def usage():
  31. prog = os.path.basename(sys.argv[0])
  32. print('Usage: %s [OPTION]...' % prog)
  33. print(' -d, display an additional level of drivers detail')
  34. print(' -h, --help display this help and exit')
  35. print('')
  36. print('Run %s from the top-level Linux kernel build directory.' % prog)
  37. class Sizes:
  38. def __init__(self, glob):
  39. self.title = glob
  40. p = Popen("size -t " + str(glob), shell=True, stdout=PIPE, stderr=PIPE)
  41. output = p.communicate()[0].splitlines()
  42. if len(output) > 2:
  43. sizes = output[-1].split()[0:4]
  44. self.text = int(sizes[0])
  45. self.data = int(sizes[1])
  46. self.bss = int(sizes[2])
  47. self.total = int(sizes[3])
  48. else:
  49. self.text = self.data = self.bss = self.total = 0
  50. def show(self, indent=""):
  51. print("%-32s %10d | %10d %10d %10d" % \
  52. (indent+self.title, self.total, self.text, self.data, self.bss))
  53. class Report:
  54. def create(filename, title, subglob=None):
  55. r = Report(filename, title)
  56. path = os.path.dirname(filename)
  57. p = Popen("ls " + str(path) + "/*.o | grep -v built-in.o",
  58. shell=True, stdout=PIPE, stderr=PIPE)
  59. glob = ' '.join(p.communicate()[0].splitlines())
  60. oreport = Report(glob, str(path) + "/*.o")
  61. oreport.sizes.title = str(path) + "/*.o"
  62. r.parts.append(oreport)
  63. if subglob:
  64. p = Popen("ls " + subglob, shell=True, stdout=PIPE, stderr=PIPE)
  65. for f in p.communicate()[0].splitlines():
  66. path = os.path.dirname(f)
  67. r.parts.append(Report.create(f, path, str(path) + "/*/built-in.o"))
  68. r.parts.sort(reverse=True)
  69. for b in r.parts:
  70. r.totals["total"] += b.sizes.total
  71. r.totals["text"] += b.sizes.text
  72. r.totals["data"] += b.sizes.data
  73. r.totals["bss"] += b.sizes.bss
  74. r.deltas["total"] = r.sizes.total - r.totals["total"]
  75. r.deltas["text"] = r.sizes.text - r.totals["text"]
  76. r.deltas["data"] = r.sizes.data - r.totals["data"]
  77. r.deltas["bss"] = r.sizes.bss - r.totals["bss"]
  78. return r
  79. create = staticmethod(create)
  80. def __init__(self, glob, title):
  81. self.glob = glob
  82. self.title = title
  83. self.sizes = Sizes(glob)
  84. self.parts = []
  85. self.totals = {"total":0, "text":0, "data":0, "bss":0}
  86. self.deltas = {"total":0, "text":0, "data":0, "bss":0}
  87. def show(self, indent=""):
  88. rule = str.ljust(indent, 80, '-')
  89. print("%-32s %10s | %10s %10s %10s" % \
  90. (indent+self.title, "total", "text", "data", "bss"))
  91. print(rule)
  92. self.sizes.show(indent)
  93. print(rule)
  94. for p in self.parts:
  95. if p.sizes.total > 0:
  96. p.sizes.show(indent)
  97. print(rule)
  98. print("%-32s %10d | %10d %10d %10d" % \
  99. (indent+"sum", self.totals["total"], self.totals["text"],
  100. self.totals["data"], self.totals["bss"]))
  101. print("%-32s %10d | %10d %10d %10d" % \
  102. (indent+"delta", self.deltas["total"], self.deltas["text"],
  103. self.deltas["data"], self.deltas["bss"]))
  104. print("\n")
  105. 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. def __cmp__(this, that):
  112. if that is None:
  113. return 1
  114. if not isinstance(that, Report):
  115. raise TypeError
  116. if this.sizes.total < that.sizes.total:
  117. return -1
  118. if this.sizes.total > that.sizes.total:
  119. return 1
  120. return 0
  121. def main():
  122. try:
  123. opts, args = getopt.getopt(sys.argv[1:], "dh", ["help"])
  124. except getopt.GetoptError as err:
  125. print('%s' % str(err))
  126. usage()
  127. sys.exit(2)
  128. driver_detail = False
  129. for o, a in opts:
  130. if o == '-d':
  131. driver_detail = True
  132. elif o in ('-h', '--help'):
  133. usage()
  134. sys.exit(0)
  135. else:
  136. assert False, "unhandled option"
  137. glob = "arch/*/built-in.o */built-in.o"
  138. vmlinux = Report.create("vmlinux", "Linux Kernel", glob)
  139. vmlinux.show()
  140. for b in vmlinux.parts:
  141. if b.totals["total"] > 0 and len(b.parts) > 1:
  142. b.show()
  143. if b.title == "drivers" and driver_detail:
  144. for d in b.parts:
  145. if d.totals["total"] > 0 and len(d.parts) > 1:
  146. d.show(" ")
  147. if __name__ == "__main__":
  148. main()