scripts: Switched to sorted sets for result notes

God, I wish Python had an OrderedSet.

This is a fix for duplicate "cycle detected" notes when using -t/--hot.
This mix of merging both _hot_notes and _notes in the HotResult class is
tricky when the underlying container is a list.

The order is unlikely to be guaranteed anyways, when different results
with different notes are folded.

And if we ever want more control over the order of notes in result
scripts we can always change this back later.
This commit is contained in:
Christopher Haster
2024-12-10 15:24:59 -06:00
parent 3e03c2ee7f
commit dd389f23ee
9 changed files with 57 additions and 59 deletions

View File

@@ -695,9 +695,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -707,7 +707,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -734,7 +734,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -890,7 +890,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -429,9 +429,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -441,7 +441,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -468,7 +468,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -624,7 +624,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -1444,9 +1444,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -1456,7 +1456,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -1483,7 +1483,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -1639,7 +1639,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -148,7 +148,7 @@ class CtxResult(co.namedtuple('CtxResult', [
RInt(size), RInt(size),
i, i,
children if children is not None else [], children if children is not None else [],
notes if notes is not None else []) notes if notes is not None else set())
def __add__(self, other): def __add__(self, other):
return CtxResult(self.file, self.function, return CtxResult(self.file, self.function,
@@ -157,8 +157,7 @@ class CtxResult(co.namedtuple('CtxResult', [
else other.i if self.i is None else other.i if self.i is None
else min(self.i, other.i), else min(self.i, other.i),
self.children + other.children, self.children + other.children,
list(co.OrderedDict.fromkeys(it.chain( self.notes | other.notes)
self.notes, other.notes)).keys()))
def openio(path, mode='r', buffering=-1): def openio(path, mode='r', buffering=-1):
@@ -682,7 +681,7 @@ def collect(obj_paths, *,
def childrenof(entry, seen=set()): def childrenof(entry, seen=set()):
# found a cycle? stop here # found a cycle? stop here
if entry.off in seen: if entry.off in seen:
return [], ['cycle detected'], True return [], {'cycle detected'}, True
# cached? # cached?
if not hasattr(childrenof, 'cache'): if not hasattr(childrenof, 'cache'):
childrenof.cache = {} childrenof.cache = {}
@@ -691,7 +690,7 @@ def collect(obj_paths, *,
# pointer? deref and include size # pointer? deref and include size
if entry.tag == 'DW_TAG_pointer_type': if entry.tag == 'DW_TAG_pointer_type':
children, notes, dirty = [], [], False children, notes, dirty = [], set(), False
if 'DW_AT_type' in entry: if 'DW_AT_type' in entry:
type = info[int(entry['DW_AT_type'].strip('<>'), 0)] type = info[int(entry['DW_AT_type'].strip('<>'), 0)]
# skip modifiers to try to find name # skip modifiers to try to find name
@@ -718,7 +717,7 @@ def collect(obj_paths, *,
elif entry.tag in { elif entry.tag in {
'DW_TAG_structure_type', 'DW_TAG_structure_type',
'DW_TAG_union_type'}: 'DW_TAG_union_type'}:
children, notes, dirty = [], [], False children, notes, dirty = [], set(), False
for child in entry.children: for child in entry.children:
if child.tag != 'DW_TAG_member': if child.tag != 'DW_TAG_member':
continue continue
@@ -740,7 +739,7 @@ def collect(obj_paths, *,
elif entry.tag in { elif entry.tag in {
'DW_TAG_base_type', 'DW_TAG_base_type',
'DW_TAG_subroutine_type'}: 'DW_TAG_subroutine_type'}:
children, notes, dirty = [], [], False children, notes, dirty = [], set(), False
# a modifier? # a modifier?
elif (entry.tag in { elif (entry.tag in {
'DW_TAG_typedef', 'DW_TAG_typedef',
@@ -758,7 +757,7 @@ def collect(obj_paths, *,
# void? # void?
elif ('DW_AT_type' not in entry elif ('DW_AT_type' not in entry
and 'DW_AT_byte_size' not in entry): and 'DW_AT_byte_size' not in entry):
children, notes = [], [], False children, notes = [], set(), False
else: else:
assert False, "Unknown dwarf entry? %r" % entry.tag assert False, "Unknown dwarf entry? %r" % entry.tag
@@ -904,9 +903,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -916,7 +915,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -943,7 +942,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -1099,7 +1098,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -695,9 +695,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -707,7 +707,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -734,7 +734,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -890,7 +890,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -875,9 +875,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -887,7 +887,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -914,7 +914,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -1070,7 +1070,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -845,9 +845,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -857,7 +857,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -884,7 +884,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -1040,7 +1040,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -146,15 +146,14 @@ class StackResult(co.namedtuple('StackResult', [
return super().__new__(cls, file, function, return super().__new__(cls, file, function,
RInt(frame), RInt(limit), RInt(frame), RInt(limit),
children if children is not None else [], children if children is not None else [],
notes if notes is not None else []) notes if notes is not None else set())
def __add__(self, other): def __add__(self, other):
return StackResult(self.file, self.function, return StackResult(self.file, self.function,
self.frame + other.frame, self.frame + other.frame,
max(self.limit, other.limit), max(self.limit, other.limit),
self.children + other.children, self.children + other.children,
list(co.OrderedDict.fromkeys(it.chain( self.notes | other.notes)
self.notes, other.notes)).keys()))
def openio(path, mode='r', buffering=-1): def openio(path, mode='r', buffering=-1):
@@ -768,7 +767,7 @@ def collect(obj_paths, ci_paths, *,
def childrenof(node, seen=set()): def childrenof(node, seen=set()):
# found a cycle? stop here # found a cycle? stop here
if node.name in seen: if node.name in seen:
return [], ['cycle detected'], True return [], {'cycle detected'}, True
# cached? # cached?
if not hasattr(childrenof, 'cache'): if not hasattr(childrenof, 'cache'):
childrenof.cache = {} childrenof.cache = {}
@@ -791,8 +790,8 @@ def collect(obj_paths, ci_paths, *,
dirty = dirty or dirty_ dirty = dirty or dirty_
if not dirty: if not dirty:
childrenof.cache[node.name] = children, [], dirty childrenof.cache[node.name] = children, set(), dirty
return children, [], dirty return children, set(), dirty
results = [] results = []
for obj_path in obj_paths: for obj_path in obj_paths:
@@ -935,9 +934,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -947,7 +946,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -974,7 +973,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -1130,7 +1129,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else:

View File

@@ -717,9 +717,9 @@ def table(Result, results, diff_results=None, *,
self = HotResult._make(r) self = HotResult._make(r)
self._hot_i = i self._hot_i = i
self._hot_children = children if children is not None else [] self._hot_children = children if children is not None else []
self._hot_notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else set()
if hasattr(Result_, '_notes'): if hasattr(Result_, '_notes'):
self._hot_notes.extend(getattr(r, r._notes)) self._hot_notes.update(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
@@ -729,7 +729,7 @@ def table(Result, results, diff_results=None, *,
else other._hot_i if self._hot_i is None else other._hot_i if self._hot_i is None
else min(self._hot_i, other._hot_i), else min(self._hot_i, other._hot_i),
self._hot_children + other._hot_children, self._hot_children + other._hot_children,
self._hot_notes + other._hot_notes) self._hot_notes | other._hot_notes)
results_ = [] results_ = []
for r in results: for r in results:
@@ -756,7 +756,7 @@ def table(Result, results, diff_results=None, *,
# found a cycle? # found a cycle?
if (detect_cycles if (detect_cycles
and tuple(getattr(r, k) for k in Result._by) in seen): and tuple(getattr(r, k) for k in Result._by) in seen):
hot_[-1]._hot_notes.append('cycle detected') hot_[-1]._hot_notes.add('cycle detected')
return return
# recurse? # recurse?
@@ -912,7 +912,7 @@ def table(Result, results, diff_results=None, *,
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(Result, '_notes') and r is not None: if hasattr(Result, '_notes') and r is not None:
notes = getattr(r, Result._notes) notes = sorted(getattr(r, Result._notes))
if isinstance(entry[-1], tuple): if isinstance(entry[-1], tuple):
entry[-1] = (entry[-1][0], entry[-1][1] + notes) entry[-1] = (entry[-1][0], entry[-1][1] + notes)
else: else: