def _calc_alignments_summary(self, align_helper): # Length is being cut in 3 groups so that further addition is easier to handle. # The length of every argument from the alignment helper is being checked if it # is longer than the longest until now. In that case the length is being saved. for key in db["task_info"]: if len(str(getattr(align_helper, key))) > db["task_info"][key]: db["task_info"][key] = len(str(getattr(align_helper, key))) for key in db["runtime_info"]: if len(str(getattr(align_helper, key))) > db["runtime_info"][key]: db["runtime_info"][key] = len(str(getattr(align_helper, key))) if args.summary_extended: for key in db["inter_times"]: if len(str(getattr(align_helper, key))) > db["inter_times"][key]: db["inter_times"][key] = len(str(getattr(align_helper, key))) def print(self): self._task_stats() fmt = self._format_stats() if not args.csv_summary: print("\nSummary") self._print_header() self._column_titles() for i in range(len(self._body)): fd_sum.write(fmt.format(*tuple(self._body[i])) + "\n") class Task(object): """ The class is used to handle the information of a given task.""" def __init__(self, id, tid, cpu, comm): self.id = id self.tid = tid self.cpu = cpu self.comm = comm self.pid = None self._time_in = None self._time_out = None def schedule_in_at(self, time): """set the time where the task was scheduled in""" self._time_in = time def schedule_out_at(self, time): """set the time where the task was scheduled out""" self._time_out = time def time_out(self, unit="s"): """return time where a given task was scheduled out""" factor = time_uniter(unit) return self._time_out * decimal.Decimal(factor) def time_in(self, unit="s"): """return time where a given task was scheduled in""" factor = time_uniter(unit) return self._time_in * decimal.Decimal(factor) def runtime(self, unit="us"): factor = time_uniter(unit) return (self._time_out - self._time_in) * decimal.Decimal(factor) def update_pid(self, pid): self.pid = pid def _task_id(pid, cpu): """returns a "unique-enough" identifier, please do not change""" return "{}-{}".format(pid, cpu) def _filter_non_printable(unfiltered): """comm names may contain loony chars like '\x00000'""" filtered = "" for char in unfiltered: if char not in string.printable: continue filtered += char return filtered def _fmt_header(): separator, fix_csv_align = _prepare_fmt_sep() fmt = "{{:>{}}}".format(LEN_SWITCHED_IN*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_SWITCHED_OUT*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_CPU*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_PID*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_TID*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_RUNTIME*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_OUT_IN*fix_csv_align) if args.extended_times: fmt += "{}{{:>{}}}".format(separator, LEN_OUT_OUT*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_IN_IN*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_IN_OUT*fix_csv_align) return fmt def _fmt_body(): separator, fix_csv_align = _prepare_fmt_sep() decimal_precision, time_precision = _prepare_fmt_precision() fmt = "{{}}{{:{}.{}f}}".format(LEN_SWITCHED_IN*fix_csv_align, decimal_precision) fmt += "{}{{:{}.{}f}}".format( separator, LEN_SWITCHED_OUT*fix_csv_align, decimal_precision ) fmt += "{}{{:{}d}}".format(separator, LEN_CPU*fix_csv_align) fmt += "{}{{:{}d}}".format(separator, LEN_PID*fix_csv_align) fmt += "{}{{}}{{:{}d}}{{}}".format(separator, LEN_TID*fix_csv_align) fmt += "{}{{}}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align) fmt += "{}{{:{}.{}f}}".format(separator, LEN_RUNTIME*fix_csv_align, time_precision) if args.extended_times: fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_IN*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_OUT*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}".format(separator, LEN_IN_IN*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}{{}}".format( separator, LEN_IN_OUT*fix_csv_align, time_precision ) else: fmt += "{}{{:{}.{}f}}{{}}".format( separator, LEN_OUT_IN*fix_csv_align, time_precision ) return fmt def _print_header(): fmt = _fmt_header() header = ("Switched-In", "Switched-Out", "CPU", "PID", "TID", "Comm", "Runtime", "Time Out-In") if args.extended_times: header += ("Time Out-Out", "Time In-In", "Time In-Out") fd_task.write(fmt.format(*header) + "\n") def _print_task_finish(task): """calculating every entry of a row and printing it immediately""" c_row_set = "" c_row_reset = "" out_in = -1 out_out = -1 in_in = -1 in_out = -1 fmt = _fmt_body() # depending on user provided highlight option we change the color # for particular tasks if str(task.tid) in args.highlight_tasks_map: c_row_set = _COLORS[args.highlight_tasks_map[str(task.tid)]] c_row_reset = _COLORS["reset"] if task.comm in args.highlight_tasks_map: c_row_set = _COLORS[args.highlight_tasks_map[task.comm]] c_row_reset = _COLORS["reset"] # grey-out entries if PID == TID, they # are identical, no threaded model so the # thread id (tid) do not matter c_tid_set = "" c_tid_reset = "" if task.pid == task.tid: c_tid_set = _COLORS["grey"] c_tid_reset = _COLORS["reset"] if task.tid in db["tid"]: # get last task of tid last_tid_task = db["tid"][task.tid][-1] # feed the timespan calculate, last in tid db # and second the current one timespan_gap_tid = Timespans() timespan_gap_tid.feed(last_tid_task) timespan_gap_tid.feed(task) out_in = timespan_gap_tid.out_in out_out = timespan_gap_tid.out_out in_in = timespan_gap_tid.in_in in_out = timespan_gap_tid.in_out if args.extended_times: line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu, task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm, task.runtime(time_unit), out_in, out_out, in_in, in_out, c_row_reset) + "\n" else: line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu, task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm, task.runtime(time_unit), out_in, c_row_reset) + "\n" try: fd_task.write(line_out) except(IOError): # don't mangle the output if user SIGINT this script sys.exit() def _record_cleanup(_list): """ no need to store more then one element if --summarize is not enabled """ if not args.summary and len(_list) > 1: _list = _list[len(_list) - 1 :] def _record_by_tid(task): tid = task.tid if tid not in db["tid"]: db["tid"][tid] = [] db["tid"][tid].append(task) _record_cleanup(db["tid"][tid]) def _record_by_cpu(task): cpu = task.cpu if cpu not in db["cpu"]: db["cpu"][cpu] = [] db["cpu"][cpu].append(task) _record_cleanup(db["cpu"][cpu]) def _record_global(task): """record all executed task, ordered by finish chronological""" db["global"].append(task) _record_cleanup(db["global"]) def _handle_task_finish(tid, cpu, time, perf_sample_dict): if tid == 0: return _id = _task_id(tid, cpu) if _id not in db["running"]: # may happen, if we missed the switch to # event. Seen in combination with --exclude-perf # where the start is filtered out, but not the # switched in. Probably a bug in exclude-perf # option. return task = db["running"][_id] task.schedule_out_at(time) # record tid, during schedule in the tid # is not available, update now pid = int(perf_sample_dict["sample"]["pid"]) task.update_pid(pid) del db["running"][_id] # print only tasks which are not being filtered and no print of trace # for summary only, but record every task. if not _limit_filtered(tid, pid, task.comm) and not args.summary_only: _print_task_finish(task) _record_by_tid(task) _record_by_cpu(task) _record_global(task) def _handle_task_start(tid, cpu, comm, time): if tid == 0: return if tid in args.tid_renames: comm = args.tid_renames[tid] _id = _task_id(tid, cpu) if _id in db["running"]: # handle corner cases where already running tasks # are switched-to again - saw this via --exclude-perf # recorded traces. We simple ignore this "second start" # event. return assert _id not in db["running"] task = Task(_id, tid, cpu, comm) task.schedule_in_at(time) db["running"][_id] = task def _time_to_internal(time_ns): """ To prevent float rounding errors we use Decimal internally """ return decimal.Decimal(time_ns) / decimal.Decimal(1e9) def _limit_filtered(tid, pid, comm): if args.filter_tasks: if str(tid) in args.filter_tasks or comm in args.filter_tasks: return True else: return False if args.limit_to_tasks: if str(tid) in args.limit_to_tasks or comm in args.limit_to_tasks: return False else: return True def _argument_filter_sanity_check(): if args.limit_to_tasks and args.filter_tasks: sys.exit("Error: Filter and Limit at the same time active.") if args.extended_times and args.summary_only: sys.exit("Error: Summary only and extended times active.") if args.time_limit and ":" not in args.time_limit: sys.exit( "Error: No bound set for time limit. Please set bound by ':' e.g :123." ) if args.time_limit and (args.summary or args.summary_only or args.summary_extended): sys.exit("Error: Cannot set time limit and print summary") if args.csv_summary: args.summary = True if args.csv == args.csv_summary: sys.exit("Error: Chosen files for csv and csv summary are the same") if args.csv and (args.summary_extended or args.summary) and not args.csv_summary: sys.exit("Error: No file chosen to write summary to. Choose with --csv-summary " "<file>") if args.csv and args.summary_only: sys.exit("Error: --csv chosen and --summary-only. Standard task would not be" "written to csv file.") def _argument_prepare_check(): global time_unit, fd_task, fd_sum if args.filter_tasks: args.filter_tasks = args.filter_tasks.split(",") if args.limit_to_tasks: args.limit_to_tasks = args.limit_to_tasks.split(",") if args.time_limit: args.time_limit = args.time_limit.split(":") for rename_tuple in args.rename_comms_by_tids.split(","): tid_name = rename_tuple.split(":") if len(tid_name) != 2: continue args.tid_renames[int(tid_name[0])] = tid_name[1] args.highlight_tasks_map = dict() for highlight_tasks_tuple in args.highlight_tasks.split(","): tasks_color_map = highlight_tasks_tuple.split(":") # default highlight color to red if no color set by user if len(tasks_color_map) == 1: tasks_color_map.append("red") if args.highlight_tasks and tasks_color_map[1].lower() not in _COLORS: sys.exit( "Error: Color not defined, please choose from grey,red,green,yellow,blue," "violet" ) if len(tasks_color_map) != 2: continue args.highlight_tasks_map[tasks_color_map[0]] = tasks_color_map[1] time_unit = "us" if args.ns: time_unit = "ns" elif args.ms: time_unit = "ms" fd_task = sys.stdout if args.csv: args.stdio_color = "never" fd_task = open(args.csv, "w") print("generating csv at",args.csv,) fd_sum = sys.stdout if args.csv_summary: args.stdio_color = "never" fd_sum = open(args.csv_summary, "w") print("generating csv summary at",args.csv_summary) if not args.csv: args.summary_only = True def _is_within_timelimit(time): """ Check if a time limit was given by parameter, if so ignore the rest. If not, process the recorded trace in its entirety. """ if not args.time_limit: return True lower_time_limit = args.time_limit[0] upper_time_limit = args.time_limit[1] # check for upper limit if upper_time_limit == "": if time >= decimal.Decimal(lower_time_limit): return True # check for lower limit if lower_time_limit == "": if time <= decimal.Decimal(upper_time_limit): return True # quit if time exceeds upper limit. Good for big datasets else: quit() if lower_time_limit != "" and upper_time_limit != "": if (time >= decimal.Decimal(lower_time_limit) and time <= decimal.Decimal(upper_time_limit)): return True # quit if time exceeds upper limit. Good for big datasets elif time > decimal.Decimal(upper_time_limit): quit() def _prepare_fmt_precision(): decimal_precision = 6 time_precision = 3 if args.ns: decimal_precision = 9 time_precision = 0 return decimal_precision, time_precision def _prepare_fmt_sep(): separator = " " fix_csv_align = 1 if args.csv or args.csv_summary: separator = ";" fix_csv_align = 0 return separator, fix_csv_align def trace_unhandled(event_name, context, event_fields_dict, perf_sample_dict): pass def trace_begin(): _parse_args() _check_color() _init_db() if not args.summary_only: _print_header() def trace_end(): if args.summary or args.summary_extended or args.summary_only: Summary().print() def sched__sched_switch(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, prev_comm, prev_pid, prev_prio, prev_state, next_comm, next_pid, next_prio, perf_sample_dict): # ignore common_secs & common_nsecs cause we need # high res timestamp anyway, using the raw value is # faster time = _time_to_internal(perf_sample_dict["sample"]["time"]) if not _is_within_timelimit(time): # user specific --time-limit a:b set return next_comm = _filter_non_printable(next_comm) _handle_task_finish(prev_pid, common_cpu, time, perf_sample_dict) _handle_task_start(next_pid, common_cpu, next_comm, time)Lines 501–934 of 934. Previous lines
def _calc_alignments_summary(self, align_helper): # Length is being cut in 3 groups so that further addition is easier to handle. # The length of every argument from the alignment helper is being checked if it # is longer than the longest until now. In that case the length is being saved. for key in db["task_info"]: if len(str(getattr(align_helper, key))) > db["task_info"][key]: db["task_info"][key] = len(str(getattr(align_helper, key))) for key in db["runtime_info"]: if len(str(getattr(align_helper, key))) > db["runtime_info"][key]: db["runtime_info"][key] = len(str(getattr(align_helper, key))) if args.summary_extended: for key in db["inter_times"]: if len(str(getattr(align_helper, key))) > db["inter_times"][key]: db["inter_times"][key] = len(str(getattr(align_helper, key))) def print(self): self._task_stats() fmt = self._format_stats() if not args.csv_summary: print("\nSummary") self._print_header() self._column_titles() for i in range(len(self._body)): fd_sum.write(fmt.format(*tuple(self._body[i])) + "\n") class Task(object): """ The class is used to handle the information of a given task.""" def __init__(self, id, tid, cpu, comm): self.id = id self.tid = tid self.cpu = cpu self.comm = comm self.pid = None self._time_in = None self._time_out = None def schedule_in_at(self, time): """set the time where the task was scheduled in""" self._time_in = time def schedule_out_at(self, time): """set the time where the task was scheduled out""" self._time_out = time def time_out(self, unit="s"): """return time where a given task was scheduled out""" factor = time_uniter(unit) return self._time_out * decimal.Decimal(factor) def time_in(self, unit="s"): """return time where a given task was scheduled in""" factor = time_uniter(unit) return self._time_in * decimal.Decimal(factor) def runtime(self, unit="us"): factor = time_uniter(unit) return (self._time_out - self._time_in) * decimal.Decimal(factor) def update_pid(self, pid): self.pid = pid def _task_id(pid, cpu): """returns a "unique-enough" identifier, please do not change""" return "{}-{}".format(pid, cpu) def _filter_non_printable(unfiltered): """comm names may contain loony chars like '\x00000'""" filtered = "" for char in unfiltered: if char not in string.printable: continue filtered += char return filtered def _fmt_header(): separator, fix_csv_align = _prepare_fmt_sep() fmt = "{{:>{}}}".format(LEN_SWITCHED_IN*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_SWITCHED_OUT*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_CPU*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_PID*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_TID*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_RUNTIME*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_OUT_IN*fix_csv_align) if args.extended_times: fmt += "{}{{:>{}}}".format(separator, LEN_OUT_OUT*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_IN_IN*fix_csv_align) fmt += "{}{{:>{}}}".format(separator, LEN_IN_OUT*fix_csv_align) return fmt def _fmt_body(): separator, fix_csv_align = _prepare_fmt_sep() decimal_precision, time_precision = _prepare_fmt_precision() fmt = "{{}}{{:{}.{}f}}".format(LEN_SWITCHED_IN*fix_csv_align, decimal_precision) fmt += "{}{{:{}.{}f}}".format( separator, LEN_SWITCHED_OUT*fix_csv_align, decimal_precision ) fmt += "{}{{:{}d}}".format(separator, LEN_CPU*fix_csv_align) fmt += "{}{{:{}d}}".format(separator, LEN_PID*fix_csv_align) fmt += "{}{{}}{{:{}d}}{{}}".format(separator, LEN_TID*fix_csv_align) fmt += "{}{{}}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align) fmt += "{}{{:{}.{}f}}".format(separator, LEN_RUNTIME*fix_csv_align, time_precision) if args.extended_times: fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_IN*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_OUT*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}".format(separator, LEN_IN_IN*fix_csv_align, time_precision) fmt += "{}{{:{}.{}f}}{{}}".format( separator, LEN_IN_OUT*fix_csv_align, time_precision ) else: fmt += "{}{{:{}.{}f}}{{}}".format( separator, LEN_OUT_IN*fix_csv_align, time_precision ) return fmt def _print_header(): fmt = _fmt_header() header = ("Switched-In", "Switched-Out", "CPU", "PID", "TID", "Comm", "Runtime", "Time Out-In") if args.extended_times: header += ("Time Out-Out", "Time In-In", "Time In-Out") fd_task.write(fmt.format(*header) + "\n") def _print_task_finish(task): """calculating every entry of a row and printing it immediately""" c_row_set = "" c_row_reset = "" out_in = -1 out_out = -1 in_in = -1 in_out = -1 fmt = _fmt_body() # depending on user provided highlight option we change the color # for particular tasks if str(task.tid) in args.highlight_tasks_map: c_row_set = _COLORS[args.highlight_tasks_map[str(task.tid)]] c_row_reset = _COLORS["reset"] if task.comm in args.highlight_tasks_map: c_row_set = _COLORS[args.highlight_tasks_map[task.comm]] c_row_reset = _COLORS["reset"] # grey-out entries if PID == TID, they # are identical, no threaded model so the # thread id (tid) do not matter c_tid_set = "" c_tid_reset = "" if task.pid == task.tid: c_tid_set = _COLORS["grey"] c_tid_reset = _COLORS["reset"] if task.tid in db["tid"]: # get last task of tid last_tid_task = db["tid"][task.tid][-1] # feed the timespan calculate, last in tid db # and second the current one timespan_gap_tid = Timespans() timespan_gap_tid.feed(last_tid_task) timespan_gap_tid.feed(task) out_in = timespan_gap_tid.out_in out_out = timespan_gap_tid.out_out in_in = timespan_gap_tid.in_in in_out = timespan_gap_tid.in_out if args.extended_times: line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu, task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm, task.runtime(time_unit), out_in, out_out, in_in, in_out, c_row_reset) + "\n" else: line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu, task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm, task.runtime(time_unit), out_in, c_row_reset) + "\n" try: fd_task.write(line_out) except(IOError): # don't mangle the output if user SIGINT this script sys.exit() def _record_cleanup(_list): """ no need to store more then one element if --summarize is not enabled """ if not args.summary and len(_list) > 1: _list = _list[len(_list) - 1 :] def _record_by_tid(task): tid = task.tid if tid not in db["tid"]: db["tid"][tid] = [] db["tid"][tid].append(task) _record_cleanup(db["tid"][tid]) def _record_by_cpu(task): cpu = task.cpu if cpu not in db["cpu"]: db["cpu"][cpu] = [] db["cpu"][cpu].append(task) _record_cleanup(db["cpu"][cpu]) def _record_global(task): """record all executed task, ordered by finish chronological""" db["global"].append(task) _record_cleanup(db["global"]) def _handle_task_finish(tid, cpu, time, perf_sample_dict): if tid == 0: return _id = _task_id(tid, cpu) if _id not in db["running"]: # may happen, if we missed the switch to # event. Seen in combination with --exclude-perf # where the start is filtered out, but not the # switched in. Probably a bug in exclude-perf # option. return task = db["running"][_id] task.schedule_out_at(time) # record tid, during schedule in the tid # is not available, update now pid = int(perf_sample_dict["sample"]["pid"]) task.update_pid(pid) del db["running"][_id] # print only tasks which are not being filtered and no print of trace # for summary only, but record every task. if not _limit_filtered(tid, pid, task.comm) and not args.summary_only: _print_task_finish(task) _record_by_tid(task) _record_by_cpu(task) _record_global(task) def _handle_task_start(tid, cpu, comm, time): if tid == 0: return if tid in args.tid_renames: comm = args.tid_renames[tid] _id = _task_id(tid, cpu) if _id in db["running"]: # handle corner cases where already running tasks # are switched-to again - saw this via --exclude-perf # recorded traces. We simple ignore this "second start" # event. return assert _id not in db["running"] task = Task(_id, tid, cpu, comm) task.schedule_in_at(time) db["running"][_id] = task def _time_to_internal(time_ns): """ To prevent float rounding errors we use Decimal internally """ return decimal.Decimal(time_ns) / decimal.Decimal(1e9) def _limit_filtered(tid, pid, comm): if args.filter_tasks: if str(tid) in args.filter_tasks or comm in args.filter_tasks: return True else: return False if args.limit_to_tasks: if str(tid) in args.limit_to_tasks or comm in args.limit_to_tasks: return False else: return True def _argument_filter_sanity_check(): if args.limit_to_tasks and args.filter_tasks: sys.exit("Error: Filter and Limit at the same time active.") if args.extended_times and args.summary_only: sys.exit("Error: Summary only and extended times active.") if args.time_limit and ":" not in args.time_limit: sys.exit( "Error: No bound set for time limit. Please set bound by ':' e.g :123." ) if args.time_limit and (args.summary or args.summary_only or args.summary_extended): sys.exit("Error: Cannot set time limit and print summary") if args.csv_summary: args.summary = True if args.csv == args.csv_summary: sys.exit("Error: Chosen files for csv and csv summary are the same") if args.csv and (args.summary_extended or args.summary) and not args.csv_summary: sys.exit("Error: No file chosen to write summary to. Choose with --csv-summary " "<file>") if args.csv and args.summary_only: sys.exit("Error: --csv chosen and --summary-only. Standard task would not be" "written to csv file.") def _argument_prepare_check(): global time_unit, fd_task, fd_sum if args.filter_tasks: args.filter_tasks = args.filter_tasks.split(",") if args.limit_to_tasks: args.limit_to_tasks = args.limit_to_tasks.split(",") if args.time_limit: args.time_limit = args.time_limit.split(":") for rename_tuple in args.rename_comms_by_tids.split(","): tid_name = rename_tuple.split(":") if len(tid_name) != 2: continue args.tid_renames[int(tid_name[0])] = tid_name[1] args.highlight_tasks_map = dict() for highlight_tasks_tuple in args.highlight_tasks.split(","): tasks_color_map = highlight_tasks_tuple.split(":") # default highlight color to red if no color set by user if len(tasks_color_map) == 1: tasks_color_map.append("red") if args.highlight_tasks and tasks_color_map[1].lower() not in _COLORS: sys.exit( "Error: Color not defined, please choose from grey,red,green,yellow,blue," "violet" ) if len(tasks_color_map) != 2: continue args.highlight_tasks_map[tasks_color_map[0]] = tasks_color_map[1] time_unit = "us" if args.ns: time_unit = "ns" elif args.ms: time_unit = "ms" fd_task = sys.stdout if args.csv: args.stdio_color = "never" fd_task = open(args.csv, "w") print("generating csv at",args.csv,) fd_sum = sys.stdout if args.csv_summary: args.stdio_color = "never" fd_sum = open(args.csv_summary, "w") print("generating csv summary at",args.csv_summary) if not args.csv: args.summary_only = True def _is_within_timelimit(time): """ Check if a time limit was given by parameter, if so ignore the rest. If not, process the recorded trace in its entirety. """ if not args.time_limit: return True lower_time_limit = args.time_limit[0] upper_time_limit = args.time_limit[1] # check for upper limit if upper_time_limit == "": if time >= decimal.Decimal(lower_time_limit): return True # check for lower limit if lower_time_limit == "": if time <= decimal.Decimal(upper_time_limit): return True # quit if time exceeds upper limit. Good for big datasets else: quit() if lower_time_limit != "" and upper_time_limit != "": if (time >= decimal.Decimal(lower_time_limit) and time <= decimal.Decimal(upper_time_limit)): return True # quit if time exceeds upper limit. Good for big datasets elif time > decimal.Decimal(upper_time_limit): quit() def _prepare_fmt_precision(): decimal_precision = 6 time_precision = 3 if args.ns: decimal_precision = 9 time_precision = 0 return decimal_precision, time_precision def _prepare_fmt_sep(): separator = " " fix_csv_align = 1 if args.csv or args.csv_summary: separator = ";" fix_csv_align = 0 return separator, fix_csv_align def trace_unhandled(event_name, context, event_fields_dict, perf_sample_dict): pass def trace_begin(): _parse_args() _check_color() _init_db() if not args.summary_only: _print_header() def trace_end(): if args.summary or args.summary_extended or args.summary_only: Summary().print() def sched__sched_switch(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, prev_comm, prev_pid, prev_prio, prev_state, next_comm, next_pid, next_prio, perf_sample_dict): # ignore common_secs & common_nsecs cause we need # high res timestamp anyway, using the raw value is # faster time = _time_to_internal(perf_sample_dict["sample"]["time"]) if not _is_within_timelimit(time): # user specific --time-limit a:b set return next_comm = _filter_non_printable(next_comm) _handle_task_finish(prev_pid, common_cpu, time, perf_sample_dict) _handle_task_start(next_pid, common_cpu, next_comm, time)