def _report_itrs(times, delim_mode=False, include_itrs=True, include_stats=True): FMT = FMTS_RPT['Itrs'] rep = '' stamps = times.stamps any_itrs = False for num in itervalues(stamps.itr_num): if num > 1: any_itrs = True break if any_itrs: rep += "\n" rep += FMT['HDR'].format('Timer' + FMT['APND'], times.name) if times.parent is not None: lin_str = _fmt_lineage(_get_lineage(times)) rep += FMT['HDR'].format('Lineage' + FMT['APND'], lin_str) if include_stats: rep += _report_itr_stats(times, delim_mode) if include_itrs and stamps.itrs: rep += "\n\nIter." itrs_order = [] is_key_active = [] for stamp in stamps.order: if stamp in stamps.itrs: itrs_order += [stamp] is_key_active += [True] # (List needed for any() usage.) for stamp in itrs_order: rep += FMT['STMP'].format(stamp) if not delim_mode: rep += "\n-----" for stamp in itrs_order: rep += "{}{{:>{}}}".format(' ' * FMT['ITR_TAB'], FMT['ITR_NAME']).format('-------') itr = 0 while any(is_key_active): # (Must be a list) next_line = FMT['ITR'].format(itr) for i, stamp in enumerate(itrs_order): if is_key_active[i]: try: val = stamps.itrs[stamp][itr] next_line += FMT['VAL'].format(val) except IndexError: next_line += FMT['NON'] is_key_active[i] = False else: next_line += FMT['NON'] if any(is_key_active): rep += next_line itr += 1 rep += "\n" for subdvsn in itervalues(times.subdvsn): for sub_times in subdvsn: rep += _report_itrs(sub_times, delim_mode, include_itrs) for par_subdvsn in itervalues(times.par_subdvsn): for par_list in itervalues(par_subdvsn): sub_with_max_tot = max(par_list, key=lambda x: x.total) rep += _report_itrs(sub_with_max_tot, delim_mode, include_itrs) return rep
def _populate_compare_stats(master): for stamp, values in iteritems(master.stamps): master.stats[stamp] = _compute_stats(values) for sub_list in itervalues(master.subdvsn): for master_sub in sub_list: _populate_compare_stats(master_sub) for sub_dict in itervalues(master.par_subdvsn): for master_sub in itervalues(sub_dict): _populate_compare_stats(master_sub)
def _write_structure(times, indent=0): strct = "\n{}{}".format(' ' * indent, times.name) if times.pos_in_parent: strct += " ({})".format(times.pos_in_parent) for sub_list in itervalues(times.subdvsn): for sub_times in sub_list: strct += _write_structure(sub_times, indent + 4) for par_dict in itervalues(times.par_subdvsn): for par_list in itervalues(par_dict): sub_with_max_tot = max(par_list, key=lambda x: x.total) strct += _write_structure(sub_with_max_tot, indent + 4) return strct
def assign_subdivisions(position, keep_subdivisions=True): # Aggregate the self-time whether subdvisions kept or not. for times in itervalues(f.t.subdvsn_awaiting): f.r.self_agg += times.self_agg for sub_list in itervalues(f.t.par_subdvsn_awaiting): sub_with_max_tot = max(sub_list, key=lambda x: x.total) f.r.self_agg += sub_with_max_tot.self_agg if keep_subdivisions: if f.t.subdvsn_awaiting: _assign_subdvsn(position) if f.t.par_subdvsn_awaiting: _assign_par_subdvsn(position) f.t.subdvsn_awaiting.clear() f.t.par_subdvsn_awaiting.clear()
def __deepcopy__(self, memo): new = type(self)() new.__dict__.update(self.__dict__) new.stamps = copy.deepcopy(self.stamps, memo) new.subdvsn = copy.deepcopy(new.subdvsn, memo) new.par_subdvsn = copy.deepcopy(self.par_subdvsn, memo) # Avoid deepcopy of parent, and update that attribute. for sub_list in itervalues(new.subdvsn): for sub in sub_list: sub.parent = new for par_dict in itervalues(new.par_subdvsn): for par_list in itervalues(par_dict): for sub in par_list: sub.parent = new return new
def __deepcopy__(self, memo): new = type(self)(self.name) new.__dict__.update(self.__dict__) new.subdvsn_awaiting = copy.deepcopy(self.subdvsn_awaiting, memo) new.par_subdvsn_awaiting = copy.deepcopy(self.par_subdvsn_awaiting, memo) for sub_times in itervalues(new.subdvsn_awaiting): sub_times.parent = new.times for sub_list in itervalues(new.par_subdvsn_awaiting): for sub_times in sub_list: sub_times.parent = new.times new.times = copy.deepcopy(self.times, memo) # Dump needs rest of stack, see mgmt_priv.copy_timer_stack() new.dump = None return new
def dump_times(): f.r.total = f.t.tmp_total - f.r.self_agg # (have already subtracted self_cut) f.r.stamps_sum = sum([v for v in itervalues(f.s.cum)]) f.r.self_agg += f.t.self_cut # (now add self_cut including self time of stop()) if f.s.itrs: for s, itr_list in iteritems(f.s.itrs): f.s.itr_max[s] = max(itr_list) nonzero_itrs = list(filter(lambda x: x > 0., itr_list)) f.s.itr_num[s] = len(nonzero_itrs) if f.s.itr_num[s] > 0: f.s.itr_min[s] = min(nonzero_itrs) else: f.s.itr_min[s] = 0. for s, val in iteritems(f.s.cum): # (for saving stamps_as_itr) if s not in f.s.itr_num: f.s.itr_num[s] = 1 f.s.itr_max[s] = val f.s.itr_min[s] = val merge_t = 0. if f.t.dump is not None: t = timer() merge.merge_times(f.t.dump, f.r) merge_t += timer() - t f.t.dump.self_agg += merge_t # Must aggregate up self time only in the case of named loop, because it # dumps directly to an already assigned subdivision, whereas normally self # time aggregates during subdivision assignment. if f.t.is_named_loop: f.r.parent.self_agg += f.r.self_agg + merge_t
def _assign_subdvsn(position): new_pos = position not in f.r.subdvsn and f.t.subdvsn_awaiting if new_pos: f.r.subdvsn[position] = list() for sub_times in itervalues(f.t.subdvsn_awaiting): sub_times.pos_in_parent = position f.r.subdvsn[position] += [sub_times] else: for sub_times in itervalues(f.t.subdvsn_awaiting): is_prev_sub = False for old_sub in f.r.subdvsn[position]: if old_sub.name == sub_times.name: is_prev_sub = True break if is_prev_sub: merge.merge_times(old_sub, sub_times) else: sub_times.pos_in_parent = position f.r.subdvsn[position].append(sub_times)
def compare(times_list=None, name=None, include_list=True, include_stats=True, delim_mode=False, format_options=None): """ Produce a formatted comparison of timing datas. Notes: If no times_list is provided, produces comparison reports on all parallel subdivisions present at the root level of the current timer. To compare parallel subdivisions at a lower level, get the times data, navigate within it to the parallel list of interest, and provide that as input here. As with report(), any further parallel subdivisions encountered have only their member with the greatest total time reported on (no branching). Args: times_list (Times, optional): list or tuple of Times objects. If not provided, uses current root timer. name (any, optional): Identifier, passed through str(). include_list (bool, optional): Display stamps hierarchy. include_stats (bool, optional): Display stamp comparison statistics. delim_mode (bool, optional): If True, format for spreadsheet. format_options (None, optional): Formatting options, see below. Formatting Keywords & Defaults: Human-readable Mode - 'stamp_name_width': 18 - 'list_column_width': 12 - 'list_tab_width': 2 - 'stat_column_width': 8 - 'stat_tab_width': 2 - 'indent_symbol: ' ' (one space) Delimited Mode - 'delimiter': '\t' (tab) - 'ident_symbol': '+' Returns: str: Times data comparison as formatted string. Raises: TypeError: If any element of provided collection is not a Times object. """ if times_list is None: rep = '' for par_dict in itervalues(f.root.times.par_subdvsn): for par_name, par_list in iteritems(par_dict): rep += report_loc.compare(par_list, par_name, include_list, include_stats, delim_mode, format_options) else: if not isinstance(times_list, (list, tuple)): raise TypeError( "Expected a list/tuple of times instances for param 'times_list'." ) if not all([isinstance(times, Times) for times in times_list]): raise TypeError( "At least one member of param 'times_list' is not a Times object." ) rep = report_loc.compare(times_list, name, include_list, include_stats, delim_mode, format_options) return rep