ksize.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #!/usr/bin/env python
  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. from string import join
  31. def usage():
  32. prog = os.path.basename(sys.argv[0])
  33. print 'Usage: %s [OPTION]...' % (prog)
  34. print ' -d, display an additional level of drivers detail'
  35. print ' -h, --help display this help and exit'
  36. print ''
  37. print 'Run %s from the top-level Linux kernel build directory.' % (prog)
  38. class Sizes:
  39. def __init__(self, glob):
  40. self.title = glob
  41. p = Popen("size -t " + glob, shell=True, stdout=PIPE, stderr=PIPE)
  42. output = p.communicate()[0].splitlines()
  43. if len(output) > 2:
  44. sizes = output[-1].split()[0:4]
  45. self.text = int(sizes[0])
  46. self.data = int(sizes[1])
  47. self.bss = int(sizes[2])
  48. self.total = int(sizes[3])
  49. else:
  50. self.text = self.data = self.bss = self.total = 0
  51. def show(self, indent=""):
  52. print "%-32s %10d | %10d %10d %10d" % \
  53. (indent+self.title, self.total, self.text, self.data, self.bss)
  54. class Report:
  55. def create(filename, title, subglob=None):
  56. r = Report(filename, title)
  57. path = os.path.dirname(filename)
  58. p = Popen("ls " + path + "/*.o | grep -v built-in.o",
  59. shell=True, stdout=PIPE, stderr=PIPE)
  60. glob = join(p.communicate()[0].splitlines())
  61. oreport = Report(glob, path + "/*.o")
  62. oreport.sizes.title = path + "/*.o"
  63. r.parts.append(oreport)
  64. if subglob:
  65. p = Popen("ls " + subglob, shell=True, stdout=PIPE, stderr=PIPE)
  66. for f in p.communicate()[0].splitlines():
  67. path = os.path.dirname(f)
  68. r.parts.append(Report.create(f, path, path + "/*/built-in.o"))
  69. r.parts.sort(reverse=True)
  70. for b in r.parts:
  71. r.totals["total"] += b.sizes.total
  72. r.totals["text"] += b.sizes.text
  73. r.totals["data"] += b.sizes.data
  74. r.totals["bss"] += b.sizes.bss
  75. r.deltas["total"] = r.sizes.total - r.totals["total"]
  76. r.deltas["text"] = r.sizes.text - r.totals["text"]
  77. r.deltas["data"] = r.sizes.data - r.totals["data"]
  78. r.deltas["bss"] = r.sizes.bss - r.totals["bss"]
  79. return r
  80. create = staticmethod(create)
  81. def __init__(self, glob, title):
  82. self.glob = glob
  83. self.title = title
  84. self.sizes = Sizes(glob)
  85. self.parts = []
  86. self.totals = {"total":0, "text":0, "data":0, "bss":0}
  87. self.deltas = {"total":0, "text":0, "data":0, "bss":0}
  88. def show(self, indent=""):
  89. rule = str.ljust(indent, 80, '-')
  90. print "%-32s %10s | %10s %10s %10s" % \
  91. (indent+self.title, "total", "text", "data", "bss")
  92. print rule
  93. self.sizes.show(indent)
  94. print rule
  95. for p in self.parts:
  96. if p.sizes.total > 0:
  97. p.sizes.show(indent)
  98. print rule
  99. print "%-32s %10d | %10d %10d %10d" % \
  100. (indent+"sum", self.totals["total"], self.totals["text"],
  101. self.totals["data"], self.totals["bss"])
  102. print "%-32s %10d | %10d %10d %10d" % \
  103. (indent+"delta", self.deltas["total"], self.deltas["text"],
  104. self.deltas["data"], self.deltas["bss"])
  105. print "\n"
  106. def __cmp__(this, that):
  107. if that is None:
  108. return 1
  109. if not isinstance(that, Report):
  110. raise TypeError
  111. if this.sizes.total < that.sizes.total:
  112. return -1
  113. if this.sizes.total > that.sizes.total:
  114. return 1
  115. return 0
  116. def main():
  117. try:
  118. opts, args = getopt.getopt(sys.argv[1:], "dh", ["help"])
  119. except getopt.GetoptError, err:
  120. print '%s' % str(err)
  121. usage()
  122. sys.exit(2)
  123. driver_detail = False
  124. for o, a in opts:
  125. if o == '-d':
  126. driver_detail = True
  127. elif o in ('-h', '--help'):
  128. usage()
  129. sys.exit(0)
  130. else:
  131. assert False, "unhandled option"
  132. glob = "arch/*/built-in.o */built-in.o"
  133. vmlinux = Report.create("vmlinux", "Linux Kernel", glob)
  134. vmlinux.show()
  135. for b in vmlinux.parts:
  136. if b.totals["total"] > 0 and len(b.parts) > 1:
  137. b.show()
  138. if b.title == "drivers" and driver_detail:
  139. for d in b.parts:
  140. if d.totals["total"] > 0 and len(d.parts) > 1:
  141. d.show(" ")
  142. if __name__ == "__main__":
  143. main()