scripts: Prevented i/children/notes result field collisions

Without this, naming a column i/children/notes in csv.py could cause
things to break. Unlikely for children/notes, but very likely for i,
especially when benchmarking.

Unfortunately namedtuple makes this tricky. I _want_ to just rename
these to _i/_children/_notes and call the problem solved, but namedtuple
reserves all underscore-prefixed fields for its own use.

As a workaround, the table renderer now looks for _i/_children/_notes at
the _class_ level, as an optional name of which namedtuple field to use.
This way Result types can stay lightweight namedtuples while including
extra table rendering info without risk of conflicts.

This also makes the HotResult type a bit more funky, but that's not a
big deal.
This commit is contained in:
Christopher Haster
2024-12-02 19:23:42 -06:00
parent 183ede1b83
commit 8526cd9cf1
9 changed files with 296 additions and 243 deletions
+32 -27
View File
@@ -509,29 +509,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -555,20 +558,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -710,8 +713,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -725,7 +728,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -759,7 +764,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -779,7 +784,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+32 -27
View File
@@ -413,29 +413,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -459,20 +462,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -614,8 +617,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -629,7 +632,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -663,7 +668,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -683,7 +688,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+32 -27
View File
@@ -1425,29 +1425,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -1471,20 +1474,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -1626,8 +1629,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -1641,7 +1644,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -1675,7 +1680,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -1695,7 +1700,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+35 -27
View File
@@ -134,6 +134,9 @@ class CtxResult(co.namedtuple('CtxResult', [
_fields = ['size'] _fields = ['size']
_sort = ['size'] _sort = ['size']
_types = {'size': RInt} _types = {'size': RInt}
_i = 'i'
_children = 'children'
_notes = 'notes'
__slots__ = () __slots__ = ()
def __new__(cls, file='', function='', size=0, def __new__(cls, file='', function='', size=0,
@@ -739,29 +742,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -785,20 +791,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -940,8 +946,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -955,7 +961,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -989,7 +997,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -1009,7 +1017,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+32 -27
View File
@@ -509,29 +509,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -555,20 +558,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -710,8 +713,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -725,7 +728,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -759,7 +764,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -779,7 +784,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+33 -27
View File
@@ -151,6 +151,7 @@ class PerfResult(co.namedtuple('PerfResult', [
'cycles': RInt, 'cycles': RInt,
'bmisses': RInt, 'branches': RInt, 'bmisses': RInt, 'branches': RInt,
'cmisses': RInt, 'caches': RInt} 'cmisses': RInt, 'caches': RInt}
_children = 'children'
__slots__ = () __slots__ = ()
def __new__(cls, file='', function='', line=0, def __new__(cls, file='', function='', line=0,
@@ -815,29 +816,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -861,20 +865,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -1016,8 +1020,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -1031,7 +1035,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -1065,7 +1071,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -1085,7 +1091,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+33 -27
View File
@@ -139,6 +139,7 @@ class PerfBdResult(co.namedtuple('PerfBdResult', [
_fields = ['readed', 'proged', 'erased'] _fields = ['readed', 'proged', 'erased']
_sort = ['erased', 'proged', 'readed'] _sort = ['erased', 'proged', 'readed']
_types = {'readed': RInt, 'proged': RInt, 'erased': RInt} _types = {'readed': RInt, 'proged': RInt, 'erased': RInt}
_children = 'children'
__slots__ = () __slots__ = ()
def __new__(cls, file='', function='', line=0, def __new__(cls, file='', function='', line=0,
@@ -778,29 +779,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -824,20 +828,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -979,8 +983,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -994,7 +998,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -1028,7 +1034,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -1048,7 +1054,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+33 -27
View File
@@ -127,6 +127,7 @@ class StackResult(co.namedtuple('StackResult', [
_fields = ['frame', 'limit'] _fields = ['frame', 'limit']
_sort = ['limit', 'frame'] _sort = ['limit', 'frame']
_types = {'frame': RInt, 'limit': RInt} _types = {'frame': RInt, 'limit': RInt}
_children = 'children'
__slots__ = () __slots__ = ()
def __new__(cls, file='', function='', frame=0, limit=0, def __new__(cls, file='', function='', frame=0, limit=0,
@@ -361,29 +362,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -407,20 +411,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -562,8 +566,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -577,7 +581,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -611,7 +617,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -631,7 +637,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",
+34 -27
View File
@@ -134,6 +134,8 @@ class StructResult(co.namedtuple('StructResult', [
_fields = ['size', 'align'] _fields = ['size', 'align']
_sort = ['size', 'align'] _sort = ['size', 'align']
_types = {'size': RInt, 'align': RInt} _types = {'size': RInt, 'align': RInt}
_i = 'i'
_children = 'children'
__slots__ = () __slots__ = ()
def __new__(cls, file='', struct='', size=0, align=0, def __new__(cls, file='', struct='', size=0, align=0,
@@ -604,29 +606,32 @@ def table(Result, results, diff_results=None, *,
# reduce children to hot paths? only used by some scripts # reduce children to hot paths? only used by some scripts
if hot: if hot:
# subclass to reintroduce __dict__ # subclass to reintroduce __dict__
class HotResult(Result): Result_ = Result
i = None class HotResult(Result_):
children = None _i = '_hot_i'
notes = None _children = '_hot_children'
_notes = '_hot_notes'
def __new__(cls, r, i=None, children=None, notes=None): def __new__(cls, r, i=None, children=None, notes=None):
self = HotResult._make(r) self = HotResult._make(r)
self.i = i self._hot_i = i
self.children = children if children is not None else [] self._hot_children = children if children is not None else []
self.notes = notes if notes is not None else [] self._hot_notes = notes if notes is not None else []
if hasattr(r, 'notes'): if hasattr(Result_, '_notes'):
self.notes.extend(r.notes) self._hot_notes.extend(getattr(r, r._notes))
return self return self
def __add__(self, other): def __add__(self, other):
return HotResult( return HotResult(
Result.__add__(self, other), Result_.__add__(self, other),
self.i if other.i is None self._hot_i if other._hot_i is None
else other.i if self.i is None else other._hot_i if self._hot_i is None
else min(self.i, other.i), else min(self._hot_i, other._hot_i),
self.children + other.children, self._hot_children + other._hot_children,
self.notes + other.notes) self._hot_notes + other._hot_notes)
def hot_(results_, depth_): results_ = []
for r in results:
hot_ = [] hot_ = []
def recurse(results_, depth_, seen=set()): def recurse(results_, depth_, seen=set()):
nonlocal hot_ nonlocal hot_
@@ -650,20 +655,20 @@ 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].notes.append('cycle detected') hot_[-1]._hot_notes.append('cycle detected')
return return
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {tuple(getattr(r, k) for k in Result._by)}) seen | {tuple(getattr(r, k) for k in Result._by)})
recurse(results_, depth_) recurse(getattr(r, Result._children), depth-1)
return hot_ results_.append(HotResult(r, children=hot_))
results = [r._replace(children=hot_(r.children, depth-1)) Result = HotResult
for r in results] results = results_
# organize by name # organize by name
table = { table = {
@@ -805,8 +810,8 @@ def table(Result, results, diff_results=None, *,
getattr(r, k, None), getattr(r, k, None),
getattr(diff_r, k, None))))) getattr(diff_r, k, None)))))
# append any notes # append any notes
if hasattr(r, 'notes'): if hasattr(Result, '_notes'):
entry[-1][1].extend(r.notes) entry[-1][1].extend(getattr(r, Result._notes))
return entry return entry
# recursive entry helper, only used by some scripts # recursive entry helper, only used by some scripts
@@ -820,7 +825,9 @@ def table(Result, results, diff_results=None, *,
names_ = list(table_.keys()) names_ = list(table_.keys())
# sort the children layer # sort the children layer
names_.sort(key=lambda n: (getattr(table_[n], 'i', None), n)) names_.sort()
if hasattr(Result, '_i'):
names_.sort(key=lambda n: getattr(table_[n], Result._i))
if sort: if sort:
for k, reverse in reversed(sort): for k, reverse in reversed(sort):
names_.sort( names_.sort(
@@ -854,7 +861,7 @@ def table(Result, results, diff_results=None, *,
# recurse? # recurse?
if depth_ > 1: if depth_ > 1:
recurse(r.children, recurse(getattr(r, Result._children),
depth_-1, depth_-1,
seen | {name}, seen | {name},
(prefixes[2+is_last] + "|-> ", (prefixes[2+is_last] + "|-> ",
@@ -874,7 +881,7 @@ def table(Result, results, diff_results=None, *,
# recursive entries # recursive entries
if name in table and depth > 1: if name in table and depth > 1:
recurse(table[name].children, recurse(getattr(table[name], Result._children),
depth-1, depth-1,
{name}, {name},
("|-> ", ("|-> ",