plot_memory_usage.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python
  2. import os, sys
  3. import subprocess
  4. import re
  5. import math
  6. import matplotlib
  7. matplotlib.use('Agg')
  8. import matplotlib.pyplot as plt
  9. from matplotlib.ticker import FuncFormatter
  10. import numpy as np
  11. import itertools
  12. import pdb
  13. def add_event(dictionary, scale):
  14. if scale in dictionary:
  15. dictionary[scale] = dictionary[scale] + 1
  16. else:
  17. dictionary[scale] = 1
  18. def convert(num):
  19. if num >= 1048576:
  20. return '{} MB'.format((num / 1048576))
  21. elif num >= 1024:
  22. return '{} kB'.format((num / 1024))
  23. # We start from 1 - 32 bytes anyway
  24. elif num == 17:
  25. return '1 B'
  26. else:
  27. return '{} B'.format(num)
  28. def megabytes(x, pos):
  29. return '%1.f MB' % (x / 1048576)
  30. def main(arg1):
  31. print('Checking how many memory events are in the log...'),
  32. sys.stdout.flush()
  33. command = 'cat {} | grep "^dmmlib - ms all" | wc -l'.format(arg1)
  34. num_events = int(subprocess.check_output(command, shell=True))
  35. # FIXME exit if there are no events
  36. print('{}.'.format(num_events))
  37. sampling = False
  38. points_to_draw = 50000
  39. if num_events >= points_to_draw:
  40. sampling = True
  41. sample_pack = int(math.ceil(float(num_events) / points_to_draw))
  42. req_sampling_check = 0
  43. alloc_sampling_check = 0
  44. # Example: dmmlib - m 0x7f5817829178 26
  45. malloc_pattern = re.compile(r'^dmmlib - m (0x\w+) (\d+)')
  46. # Example: dmmlib - ms req 609
  47. requested_pattern = re.compile('^dmmlib - ms req (\d+)')
  48. # Example: dmmlib - ms all 1280
  49. allocated_pattern = re.compile('^dmmlib - ms all (\d+)')
  50. scale_dictionary = {}
  51. requested = []
  52. allocated = []
  53. print('Parsing the log file...')
  54. sys.stdout.flush()
  55. with open(arg1) as infile:
  56. for line in infile:
  57. malloc_match = malloc_pattern.match(line)
  58. if malloc_match:
  59. request_size = int(malloc_match.group(2))
  60. scale = int(math.ceil(math.log(request_size, 2)))
  61. # Starting bar is up to 32 bytes
  62. if scale < 5:
  63. scale = 5
  64. add_event(scale_dictionary, scale)
  65. requested_match = requested_pattern.match(line)
  66. if requested_match:
  67. if req_sampling_check == 0:
  68. requested.append(int(requested_match.group(1)))
  69. if sampling:
  70. req_sampling_check += 1
  71. else:
  72. if req_sampling_check == sample_pack - 1:
  73. req_sampling_check = 0
  74. else:
  75. req_sampling_check += 1
  76. allocated_match = allocated_pattern.match(line)
  77. if allocated_match:
  78. if alloc_sampling_check == 0:
  79. allocated.append(int(allocated_match.group(1)))
  80. if sampling:
  81. alloc_sampling_check += 1
  82. else:
  83. if alloc_sampling_check == sample_pack - 1:
  84. alloc_sampling_check = 0
  85. else:
  86. alloc_sampling_check += 1
  87. print('Done')
  88. # Histogram of requested sizes - START
  89. print('Creating a histogram plot for the requested sizes...'),
  90. sys.stdout.flush()
  91. hist_fig = plt.figure()
  92. hist_ax = hist_fig.add_subplot(111)
  93. size_data = zip(*scale_dictionary.items())
  94. hist_rects = hist_ax.bar(np.array(size_data[0]) - 4, size_data[1], width=0.2, align='center')
  95. sorted_keys = np.array(sorted(scale_dictionary.keys()))
  96. start = np.power(2, sorted_keys - 1) + 1
  97. end = np.power(2, sorted_keys)
  98. xlabels = [ '{} - {}'.format(convert(t[0]), convert(t[1])) for t in itertools.izip(start, end) ]
  99. hist_ax.set_xticks(sorted_keys - 4)
  100. hist_ax.set_xticklabels(xlabels)
  101. # Show only the xticks of the bottom X axis
  102. hist_ax.get_xaxis().tick_bottom()
  103. hist_ax.set_title('Memory request sizes')
  104. hist_ax.set_ylabel('Counts')
  105. hist_fig.autofmt_xdate()
  106. hist_fig.savefig('{}_histogram.pdf'.format(arg1))
  107. print('Done.')
  108. # Histogram of requested sizes - END
  109. # Memory usage - START
  110. print('Creating a plot for the memory utilization timeline...'),
  111. sys.stdout.flush()
  112. req_fig = plt.figure()
  113. req_ax = req_fig.add_subplot(111)
  114. req_ax.plot(requested, label='requested memory', rasterized=True)
  115. req_ax.plot(allocated, label='allocated memory', rasterized=True)
  116. req_ax.set_xticks([])
  117. req_ax.set_xlabel('Application timeline')
  118. req_ax.yaxis.set_major_formatter(FuncFormatter(megabytes))
  119. req_ax.get_yaxis().tick_left()
  120. req_ax.legend(bbox_to_anchor=(0, 1.02, 1., .102), loc=3, ncol=2,
  121. mode="expand", borderaxespad=0.)
  122. req_fig.savefig('{}_mem_usage.pdf'.format(arg1), dpi=150)
  123. print('Done.')
  124. # Memory usage - END
  125. return 0
  126. if __name__=='__main__':
  127. if len(sys.argv) < 2:
  128. sys.exit('Usage: %s trace-file' % sys.argv[0])
  129. if not os.path.exists(sys.argv[1]):
  130. sys.exit('ERROR: Trace file %s was not found!' % sys.argv[1])
  131. sys.exit(main(sys.argv[1]))