graph_cores.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. import sys, os
  4. import matplotlib
  5. matplotlib.use('Agg')
  6. from pylab import *
  7. from matplotlib.transforms import TransformedBbox
  8. class EventFactory(object):
  9. #CPU time pid cpu (si pid == -1 -> idle)
  10. cpu_event= lambda x: Event(x[0],EventFactory.Events.keys().index(x[0]),int(x[1]),int(x[2]),int(x[3]))
  11. #EVENT time pid
  12. other_event= lambda x: Event(x[0],EventFactory.Events.keys().index(x[0]),int(x[1]),int(x[2]),-1)
  13. #CONTEXT CPU cpu time (se pone pid == -2)
  14. context_switch_event= lambda x: Event(x[0] ,EventFactory.Events.keys().index(x[0]),int(x[3]),-2,int(x[2]))
  15. Events = {'LOAD': other_event,
  16. 'CPU':cpu_event,
  17. 'BLOCK': other_event,
  18. 'UNBLOCK': other_event,
  19. 'DEADLINE': other_event,
  20. 'EXIT': other_event,
  21. 'CONTEXT':context_switch_event,
  22. 'WAITING':None,
  23. 'NOT_LOAD': None,
  24. 'CPU_BLOCK': None}
  25. @classmethod
  26. def get_event(cls, event_line):
  27. splited_event_line= event_line.split()
  28. if splited_event_line[0] in EventFactory.Events.keys():
  29. return EventFactory.Events[splited_event_line[0]](splited_event_line)
  30. else:
  31. return None
  32. class Event(object):
  33. def __init__(self, event_type, event_code, time, pid, core):
  34. self.event_type= event_type
  35. self.event_code= event_code
  36. self.time= time
  37. self.pid= pid
  38. self.core= core
  39. def __str__(self):
  40. return 'Type: ' + self.event_type + ', Code: ' + str(self.event_code) + ', Time: ' + str(self.time) + ', Pid: ' + str(self.pid) + ', Core: ' + str(self.core)
  41. def parseInput(fin):
  42. ln = 0
  43. result = []
  44. cores = 0
  45. pids= 0
  46. settings = None
  47. cpus_timeline= dict()
  48. for line in fin:
  49. ln += 1
  50. vls = line.split()
  51. if line and line[0] == '#':
  52. if line.startswith('# SETTINGS '):
  53. settings = line[11:].strip()
  54. continue
  55. else:
  56. line= line[2:].strip() # Queda --> 'CONTEXT CPU cpu time
  57. event= EventFactory.get_event(line)
  58. result.append(event)
  59. if event.event_type == 'CPU':
  60. if (cores <=event.core):
  61. cores = event.core+1
  62. if event.event_type == 'LOAD':
  63. if(pids <= event.pid):
  64. pids = event.pid +1
  65. return settings, result, cores, pids
  66. def dataGathering(data, cores, pids):
  67. core_timeline= dict() # core: list(pids) NOTA: se supone que en cada tick hay un pid
  68. block_lapse= dict()
  69. for event in data:
  70. #core_time
  71. if event.core != -1:
  72. if event.core not in core_timeline: core_timeline[event.core]= []
  73. core_timeline[event.core].append(event.pid)
  74. return core_timeline
  75. def draw_cores_timeline_gannt(cores_timeline, filename):
  76. ''' pre: cores_timeline = {core: list(pid) } '''
  77. # Necesitaria tener la info algo asi como
  78. # core: {pid: ini_1,fin_1,ini_2,fin_2} (es decir por intervalos)
  79. # broken_barh necesita (inicio, longitud)
  80. colors={'pid':'#c0ffc0','switch':'#b7b7f7', 'idle':'#d0d0d0'}
  81. fig= figure(figsize=(11.8,8.3))
  82. ax = fig.add_subplot(111)
  83. title('Tareas en Core por tiempo')
  84. yticks(cores_timeline.keys())
  85. # ax.xaxis.set_major_locator(
  86. ax.xaxis.set_major_locator( IndexLocator(2,1) )
  87. #xticks(range(len(cores_timeline[0])),range(0,len(cores_timeline[0]),5))
  88. xlabel('Tiempo')
  89. ylabel('Core')
  90. ylim((-1,len(cores_timeline.keys())))
  91. ax.grid(True)
  92. for core in cores_timeline:
  93. pids_by_time= cores_timeline[core]
  94. intervals= dict()
  95. last_pid= None
  96. for time in range(len(pids_by_time)):
  97. if last_pid != pids_by_time[time]:
  98. last_pid = pids_by_time[time]
  99. if last_pid not in intervals: intervals[last_pid]= []
  100. intervals[last_pid].append((time, 1))
  101. #intervals.push((last_pid,time,1))
  102. else:
  103. #pid, time, interval_size= intervals.pop()
  104. #intervals.push((pid, time, interval_size+1))
  105. time, interval_size= intervals[last_pid].pop()
  106. intervals[last_pid].append((time, interval_size+1))
  107. for pid in intervals:
  108. if pid >= 0:
  109. rect= ax.broken_barh(intervals[pid], (core-0.25, 0.5), facecolor=colors['pid'])
  110. for init, size in intervals[pid]:
  111. ax.text(init+(size/2.0),core, str(pid), ha="center", va="center", size=9, weight='bold')
  112. elif pid == -1:
  113. rect= ax.broken_barh(intervals[pid], (core-0.25, 0.5), facecolor=colors['idle'])
  114. elif pid == -2:
  115. rect= ax.broken_barh(intervals[pid], (core-0.25, 0.5), facecolor=colors['switch'])
  116. else:
  117. print 'ERROR!'
  118. tarea_dummy = Rectangle((0, 0), 1, 1, fc=colors['pid'])
  119. switch_dummy = Rectangle((0, 0), 1, 1, fc=colors['switch'])
  120. idle_dummy = Rectangle((0, 0), 1, 1, fc=colors['idle'])
  121. legend([tarea_dummy, switch_dummy, idle_dummy], ['Tarea','Cambio de contexto','Inactivo'])
  122. tight_layout()
  123. fig.autofmt_xdate()
  124. ax.legend()
  125. savefig(filename+'.png', dpi=300, format='png')
  126. def main(argv):
  127. if len(argv) <= 1:
  128. fin = sys.stdin
  129. fout_cores_timeline= 'out_cores_timeline'
  130. else:
  131. fin = open(argv[1], 'r')
  132. preffix= argv[1]
  133. fout_cores_timeline= preffix + '_cores_timeline'
  134. print 'parsing input'
  135. settings, data, cores, pids = parseInput(fin)
  136. print 'data gathering'
  137. cores_timeline= dataGathering(data, cores, pids)
  138. print cores_timeline
  139. #todo dump de los datos
  140. print 'drawing cores timeline'
  141. draw_cores_timeline_gannt(cores_timeline, fout_cores_timeline)
  142. if __name__ == "__main__":
  143. main(sys.argv)