def do_event_menu_select(proj, event): try: a = event.predicted except AttributeError: return found = 0 i = 0 while not found: p = proj.generic_find_process( 0, "menu_select_cpu%d_%d_predicted" % (event.common_cpu, i), "menu_select") p2 = proj.generic_find_process( 0, "menu_select_cpu%d_%d_expected" % (event.common_cpu, i), "menu_select") if len(p['end_ts']) > 0 and len(p2['end_ts']) > 0 and ( p['end_ts'][-1] > event.timestamp or p2['end_ts'][-1] > event.timestamp): i += 1 continue found = 1 p['start_ts'].append(int(event.timestamp)) p['end_ts'].append(int(event.timestamp + event.predicted)) p['types'].append(colors.get_color_id("menu_select")) p['cpus'].append(event.common_cpu) p = p2 p['start_ts'].append(int(event.timestamp)) p['end_ts'].append(int(event.timestamp + event.expected)) p['types'].append(colors.get_color_id("menu_select")) p['cpus'].append(event.common_cpu)
def generic_process_start(self, process, event, build_p_stack=True): if process['type'] == "user_process" and process['pid'] == 0: return # ignore swapper event if len(process['start_ts']) > len(process['end_ts']): process['end_ts'].append(event.timestamp) if self.first_ts == 0: self.first_ts = event.timestamp self.cur_process_by_pid[process['pid']] = process if build_p_stack: p_stack = self.cur_process[event.common_cpu] if p_stack: p = p_stack[-1] if len(p['start_ts']) > len(p['end_ts']): p['end_ts'].append(event.timestamp) # mark old process to wait for cpu p['start_ts'].append(int(event.timestamp)) p['types'].append(colors.get_color_id("waiting_for_cpu")) p['cpus'].append(event.common_cpu) p_stack.append(process) else: self.cur_process[event.common_cpu] = [process] # mark process to use cpu process['start_ts'].append(event.timestamp) process['types'].append(colors.get_color_id("running")) process['cpus'].append(event.common_cpu)
def generic_process_start(self,process,event, build_p_stack=True): if process['type']=="user_process" and process['pid']==0: return # ignore swapper event if len(process['start_ts'])>len(process['end_ts']): process['end_ts'].append(event.timestamp) if self.first_ts == 0: self.first_ts = event.timestamp self.cur_process_by_pid[process['pid']] = process if build_p_stack : p_stack = self.cur_process[event.common_cpu] if p_stack: p = p_stack[-1] if len(p['start_ts'])>len(p['end_ts']): p['end_ts'].append(event.timestamp) # mark old process to wait for cpu p['start_ts'].append(int(event.timestamp)) p['types'].append(colors.get_color_id("waiting_for_cpu")) p['cpus'].append(event.common_cpu) p_stack.append(process) else: self.cur_process[event.common_cpu] = [process] # mark process to use cpu process['start_ts'].append(event.timestamp) process['types'].append(colors.get_color_id("running")) process['cpus'].append(event.common_cpu)
def generic_process_end(self,process,event, build_p_stack=True): if process['comm']=='swapper' and process['pid']==0: return # ignore swapper event if len(process['start_ts'])>len(process['end_ts']): process['end_ts'].append(event.timestamp) if build_p_stack : p_stack = self.cur_process[event.common_cpu] if p_stack: p = p_stack.pop() if p['pid'] != process['pid']: print "warning: process premption stack following failure on CPU",event.common_cpu, p['comm'],p['pid'],process['comm'],process['pid'],map(lambda a:"%s:%d"%(a['comm'],a['pid']),p_stack),event.linenumber p_stack = [] elif p['comm'] != process['comm']: # this is the fork and exec case. # fix the temporary process that had the comm of the parent # remove old pid,comm from process list del self.tmp_process[(p['pid'],p['comm'])] # add new pid,comm to process list p['comm'] = process['comm'] self.tmp_process[(p['pid'],p['comm'])] = p if len(p['start_ts'])>len(p['end_ts']): p['end_ts'].append(event.timestamp) if p_stack: p = p_stack[-1] if len(p['start_ts'])>len(p['end_ts']): p['end_ts'].append(event.timestamp) # mark old process to run on cpu p['start_ts'].append(event.timestamp) p['types'].append(colors.get_color_id("running")) p['cpus'].append(event.common_cpu)
def generic_process_end(self, process, event, build_p_stack=True): if process['type'] == "user_process" and process['pid'] == 0: return # ignore swapper event if len(process['start_ts']) > len(process['end_ts']): process['end_ts'].append(event.timestamp) if build_p_stack: p_stack = self.cur_process[event.common_cpu] if p_stack: p = p_stack.pop() if p['pid'] != process['pid']: print "warning: process premption stack following failure on CPU", event.common_cpu, p[ 'comm'], p['pid'], process['comm'], process[ 'pid'], map( lambda a: "%s:%d" % (a['comm'], a['pid']), p_stack), event.linenumber p_stack = [] if p_stack: p = p_stack[-1] if len(p['start_ts']) > len(p['end_ts']): p['end_ts'].append(event.timestamp) # mark old process to run on cpu p['start_ts'].append(event.timestamp) p['types'].append(colors.get_color_id("running")) p['cpus'].append(event.common_cpu)
def process_stats(self,start,end): fact = 100./(end-start) for tc in self.processes: starts,ends,types = tc.get_partial_tables(start,end) inds = np.where(types==colors.get_color_id("running")) tot = sum(ends[inds]-starts[inds]) tc.selection_time = int(tot) tc.selection_pc = tot*fact
def generic_process_single_event(self, process, event): if len(process['start_ts']) > len(process['end_ts']): process['end_ts'].append(event.timestamp) # mark process to use cpu process['start_ts'].append(event.timestamp) process['types'].append(colors.get_color_id("running")) process['cpus'].append(event.common_cpu) process['end_ts'].append(event.timestamp)
def generic_process_single_event(self,process,event): if len(process['start_ts'])>len(process['end_ts']): process['end_ts'].append(event.timestamp) # mark process to use cpu process['start_ts'].append(event.timestamp) process['types'].append(colors.get_color_id("running")) process['cpus'].append(event.common_cpu) process['end_ts'].append(event.timestamp)
def process_stats(self, start, end): fact = 100. / (end - start) for tc in self.processes: starts, ends, types = tc.get_partial_tables(start, end) inds = np.where(types == colors.get_color_id("running")) tot = sum(ends[inds] - starts[inds]) tc.selection_time = int(tot) tc.selection_pc = tot * fact
def do_event_sched_switch(self,event): prev = self.generic_find_process(event.prev_pid,event.prev_comm,"user_process") next = self.generic_find_process(event.next_pid,event.next_comm,"user_process") self.generic_process_end(prev,event) if event.__dict__.has_key('prev_state') and event.prev_state == 'R':# mark prev to be waiting for cpu prev['start_ts'].append(event.timestamp) prev['types'].append(colors.get_color_id("waiting_for_cpu")) prev['cpus'].append(event.common_cpu) self.generic_process_start(next,event)
def do_event_runtime_pm_status(proj, event): if proj.first_ts == 0: proj.first_ts = event.timestamp - 1 p = proj.generic_find_process( 0, "runtime_pm:%s %s" % (event.driver, event.dev), "runtime_pm") if len(p['start_ts']) > len(p['end_ts']): p['end_ts'].append(event.timestamp) if event.status != "SUSPENDED": p['start_ts'].append(int(event.timestamp)) p['types'].append( colors.get_color_id("rpm_%s" % (event.status.lower()))) p['cpus'].append(event.common_cpu)
def do_event_runtime_pm_usage(proj, event): p = proj.generic_find_process( 0, "runtime_pm_usage:%s %s" % (event.driver, event.dev), "runtime_pm") if len(p['start_ts']) > len(p['end_ts']): p['end_ts'].append(event.timestamp) if event.usage != 0: p['start_ts'].append(int(event.timestamp)) usagecolor = event.usage if usagecolor < 0: usagecolor = -1 if usagecolor > 6: usagecolor = 6 p['types'].append( colors.get_color_id("rpm_usage=%d" % (usagecolor))) p['cpus'].append(event.common_cpu)
def do_event_sched_switch(self, event): # @todo differenciate between kernel and user process prev = self.generic_find_process(event.prev_pid, event.prev_comm, "user_process", event.timestamp - 100000000) next = self.generic_find_process(event.next_pid, event.next_comm, "user_process", event.timestamp - 100000000) self.generic_process_end(prev, event) if 'prev_state' in event.__dict__ and event.prev_state == 'R': # mark prev to be waiting for cpu prev['start_ts'].append(event.timestamp) prev['types'].append(colors.get_color_id("waiting_for_cpu")) prev['cpus'].append(event.common_cpu) self.generic_process_start(next, event)
def start_cpu_idle(self, event): try: tc = self.tmp_c_states[event.cpuid] except: self.ensure_cpu_allocated(event.cpuid) tc = self.tmp_c_states[event.cpuid] if len(tc['start_ts']) > len(tc['end_ts']): tc['end_ts'].append(event.timestamp) self.missed_power_end += 1 if self.missed_power_end < 10: print("warning: missed cpu_idle end") if self.missed_power_end == 10: print("warning: missed cpu_idle end: wont warn anymore!") name = c_state_table[int(event.state)] tc['start_ts'].append(event.timestamp) tc['types'].append(colors.get_color_id(name)) process = self.generic_find_process(0, "cpu%d/%s" % (event.cpuid, name), "cpuidle") self.generic_process_start(process, event, build_p_stack=False)
def generic_process_end(self,process,event, build_p_stack=True): if process['type']=="user_process" and process['pid']==0: return # ignore swapper event if len(process['start_ts'])>len(process['end_ts']): process['end_ts'].append(event.timestamp) if build_p_stack : p_stack = self.cur_process[event.common_cpu] if p_stack: p = p_stack.pop() if p['pid'] != process['pid']: print "warning: process premption stack following failure on CPU",event.common_cpu, p['comm'],p['pid'],process['comm'],process['pid'],map(lambda a:"%s:%d"%(a['comm'],a['pid']),p_stack),event.linenumber p_stack = [] if p_stack: p = p_stack[-1] if len(p['start_ts'])>len(p['end_ts']): p['end_ts'].append(event.timestamp) # mark old process to run on cpu p['start_ts'].append(event.timestamp) p['types'].append(colors.get_color_id("running")) p['cpus'].append(event.common_cpu)
def _draw_timechart(self, gc, tc, label, base_y): bar_middle_y = self.first_bar_y + (base_y + .5) * self.bar_height points = self._gather_timechart_points(tc.start_ts, tc.end_ts, base_y, .2) overview = None if self.options.use_overview: if points.size > 500: overview = tc.get_overview_ts(self.overview_threshold) points = self._gather_timechart_points(overview[0], overview[1], base_y, .2) if self.options.remove_pids_not_on_screen and points.size == 0: return 0 if bar_middle_y + self.bar_height < self.y or bar_middle_y - self.bar_height > self.y + self.height: return 1 #quickly decide we are not on the screen self._draw_bg(gc, base_y, tc.bg_color) # we are too short in height, dont display all the labels if self.last_label >= bar_middle_y: # draw label l_w, l_h = self._draw_label(gc, label, tc.name, self.x, bar_middle_y) self.last_label = bar_middle_y - 8 else: l_w, l_h = 0, 0 if points.size != 0: # draw the middle line from end of label to end of screen if l_w != 0: # we did not draw label because too short on space gc.set_alpha(0.2) gc.move_to(self.x + l_w, bar_middle_y) gc.line_to(self.x + self.width, bar_middle_y) gc.draw_path() gc.set_alpha(0.5) # map the bars start and stop locations into screen space lower_left_pts = self.map_screen(points[:, (0, 2)]) upper_right_pts = self.map_screen(points[:, (1, 3)]) bounds = upper_right_pts - lower_left_pts if overview: # critical path, we only draw unicolor rects #calculate the mean color #print points.size gc.set_fill_color(get_aggcolor_by_id(get_color_id("overview"))) gc.set_alpha(.9) rects = column_stack((lower_left_pts, bounds)) gc.rects(rects) gc.draw_path() else: # lets display them more nicely rects = column_stack((lower_left_pts, bounds, points[:, (4)])) last_t = -1 gc.save_state() for x, y, sx, sy, i in rects: t = tc.types[i] if last_t != t: # only draw when we change color. agg will then simplify the path # note that a path only can only have one color in agg. gc.draw_path() gc.set_fill_color(get_aggcolor_by_id(int(t))) last_t = t gc.rect(x, y, sx, sy) # draw last path gc.draw_path() if tc.has_comments: for x, y, sx, sy, i in rects: if sx < 8: # not worth calculatig text size continue label.text = tc.get_comment(i) l_w, l_h = label.get_width_height(gc) if l_w < sx: offset = array( (x, y + self.bar_height * .6 / 2 - l_h / 2)) gc.translate_ctm(*offset) label.draw(gc) gc.translate_ctm(*(-offset)) if tc.max_latency > 0: # emphase events where max_latency is reached ts = tc.max_latency_ts if ts.size > 0: points = self._gather_timechart_points(ts, ts, base_y, 0) if points.size > 0: # map the bars start and stop locations into screen space gc.set_alpha(1) lower_left_pts = self.map_screen(points[:, (0, 2)]) upper_right_pts = self.map_screen(points[:, (1, 3)]) bounds = upper_right_pts - lower_left_pts rects = column_stack((lower_left_pts, bounds)) gc.rects(rects) gc.draw_path() return 1
def _draw_timechart(self,gc,tc,label,base_y): bar_middle_y = self.first_bar_y+(base_y+.5)*self.bar_height points = self._gather_timechart_points(tc.start_ts,tc.end_ts,base_y,.2) overview = None if self.options.use_overview: if points.size > 500: overview = tc.get_overview_ts(self.overview_threshold) points = self._gather_timechart_points(overview[0],overview[1],base_y,.2) if self.options.remove_pids_not_on_screen and points.size == 0: return 0 if bar_middle_y+self.bar_height < self.y or bar_middle_y-self.bar_height>self.y+self.height: return 1 #quickly decide we are not on the screen self._draw_bg(gc,base_y,tc.bg_color) # we are too short in height, dont display all the labels if self.last_label >= bar_middle_y: # draw label l_w,l_h = self._draw_label(gc,label,tc.name,self.x,bar_middle_y) self.last_label = bar_middle_y-8 else: l_w,l_h = 0,0 if points.size != 0: # draw the middle line from end of label to end of screen if l_w != 0: # we did not draw label because too short on space gc.set_alpha(0.2) gc.move_to(self.x+l_w,bar_middle_y) gc.line_to(self.x+self.width,bar_middle_y) gc.draw_path() gc.set_alpha(0.5) # map the bars start and stop locations into screen space lower_left_pts = self.map_screen(points[:,(0,2)]) upper_right_pts = self.map_screen(points[:,(1,3)]) bounds = upper_right_pts - lower_left_pts if overview: # critical path, we only draw unicolor rects #calculate the mean color #print points.size gc.set_fill_color(get_aggcolor_by_id(get_color_id("overview"))) gc.set_alpha(.9) rects=column_stack((lower_left_pts, bounds)) gc.rects(rects) gc.draw_path() else: # lets display them more nicely rects=column_stack((lower_left_pts, bounds,points[:,(4)])) last_t = -1 gc.save_state() for x,y,sx,sy,i in rects: t = tc.types[i] if last_t != t: # only draw when we change color. agg will then simplify the path # note that a path only can only have one color in agg. gc.draw_path() gc.set_fill_color(get_aggcolor_by_id(int(t))) last_t = t gc.rect(x,y,sx,sy) # draw last path gc.draw_path() if tc.has_comments: for x,y,sx,sy,i in rects: if sx<8: # not worth calculatig text size continue label.text = tc.get_comment(i) l_w,l_h = label.get_width_height(gc) if l_w < sx: offset = array((x,y+self.bar_height*.6/2-l_h/2)) gc.translate_ctm(*offset) label.draw(gc) gc.translate_ctm(*(-offset)) if tc.max_latency > 0: # emphase events where max_latency is reached ts = tc.max_latency_ts if ts.size>0: points = self._gather_timechart_points(ts,ts,base_y,0) if points.size>0: # map the bars start and stop locations into screen space gc.set_alpha(1) lower_left_pts = self.map_screen(points[:,(0,2)]) upper_right_pts = self.map_screen(points[:,(1,3)]) bounds = upper_right_pts - lower_left_pts rects=column_stack((lower_left_pts, bounds)) gc.rects(rects) gc.draw_path() return 1